#include #include #include "utils.h" #include "device.h" #include "json/parser.h" // declare of scoped vars and funcs namespace hm { const int gWaitTime = 3000; std::map gOpenTypeMap = { // NOLINT {0, "未知方式"}, {1, "密码开锁"}, {2, "刷卡开锁"}, {3, "先刷卡后密码开锁"}, {4, "先密码后刷卡开锁"}, {5, "远程开锁,如通过室内机或者平台对门口机开锁"}, {6, "开锁按钮进行开锁"}, {7, "开锁"}, {8, "密码+刷卡+组合开锁"}, {10, "密码+组合开锁"}, {11, "刷卡+组合开锁"}, {12, "多人开锁"}, {13, "钥匙开门"}, {14, "胁迫密码开门"}, {15, "二维码开门"}, {16, "目标识别开门"}, {18, "人证对比"}, {19, "证件+人证比对"}, {20, "蓝牙开门"}, {21, "个性化密码开门"}, {22, "UserID+密码"}, {23, "人脸+密码开锁"}, {24, "+密码开锁"}, {25, "+人脸开锁"}, {26, "刷卡+人脸开锁"}, {27, "人脸或密码开锁"}, {28, "或密码开锁"}, {29, "或人脸开锁"}, {30, "刷卡或人脸开锁"}, {31, "刷卡或开锁"}, {32, "+人脸+密码开锁"}, {33, "刷卡+人脸+密码开锁"}, {34, "刷卡++密码开锁"}, {35, "卡++人脸组合开锁"}, {36, "或人脸或密码"}, {37, "卡或人脸或密码开锁"}, {38, "卡或人脸开锁"}, {39, "卡++人脸+密码组合开锁"}, {40, "卡或人脸或密码开锁"}, {41, "(证件+人证比对)或刷卡或人脸"}, {42, "人证比对或刷卡(二维码)或人脸"}, {43, "DTMF开锁(包括SIPINFO,RFC2833,INBAND)"}, {44, "远程二维码开门"}, {45, "远程人脸开门"}, {46, "人证比对开门()"}, {47, "临时密码开门"}, {48, "健康码开门"}, {49, "目标识别开锁"}, {50, "目标+密码组合开锁"}, {51, "人脸+目标组合开锁"}, {52, "卡+目标组合开锁"}, {53, "目标或密码开锁"}, {54, "人脸或目标开锁"}, {55, "卡或目标开锁"}, {56, "人脸+目标+密码组合开锁"}, {57, "卡+人脸+目标组合开锁"}, {58, "卡+目标+密码组合开锁"}, {59, "人脸或目标或密码开锁"}, {60, "卡或人脸或目标开锁"}, {61, "卡或目标或密码开锁"}, {62, "卡+人脸+目标+密码组合开锁"}, {63, "卡或人脸或目标或密码开锁"} }; int onSubscribeData( LLONG handler, DWORD type, void *info, BYTE *imgBuf, DWORD bufSize, LDWORD user, int seq, void *reserved ); Device *getDeviceBySubId(const LLONG &subId); } // implement of scoped funcs namespace hm { int onSubscribeData( LLONG handler, DWORD type, void *info, BYTE *imgBuf, DWORD bufSize, LDWORD user, int seq, void *reserved ) { Device *device = getDeviceBySubId(handler); if (device == nullptr) { Log(Warn, "unrecognized subscribe uid: %ld", handler); return 0; } switch (type) { case EVENT_IVS_ACCESS_CTL: // 人脸 if (device->isFaceDevice) device->onAccessCtlEvent((DEV_EVENT_ACCESS_CTL_INFO *) info, imgBuf, bufSize); else Log(Warn, "seq[%s] is car device, but got a face event", device->seq.c_str()); break; case EVENT_IVS_TRAFFICJUNCTION: // 车辆闸机 if (!device->isFaceDevice) device->onTrafficJunctionEvent((DEV_EVENT_TRAFFICJUNCTION_INFO *) info, imgBuf, bufSize); else Log(Warn, "seq[%s] is face device, but got a car event", device->seq.c_str()); break; default: Log(Warn, "unrecognized event: %u", type); break; } return 1; } Device *getDeviceBySubId(const LLONG &subId) { for (auto &itr : gDevicesVec) if (itr->subId == subId) return itr.get(); return nullptr; } void Device::init() { NET_IN_INIT_DEVICE_ACCOUNT in; in.dwSize = sizeof in; strcpy(in.szMac, this->mac.c_str()); strcpy(in.szUserName, gConfLoginUser.c_str()); strcpy(in.szPwd, gConfLoginPass.c_str()); in.byPwdResetWay = this->reset; NET_OUT_INIT_DEVICE_ACCOUNT out; out.dwSize = sizeof out; if (CLIENT_InitDevAccount(&in, &out, gWaitTime, this->local.data())) { Log(Info, "device: seq[%s] init success", this->seq.c_str()); this->inited = true; return; } Log( Error, "device(ip[%s], mac[%s], seq[%s]) init fail", this->ip.c_str(), this->mac.c_str(), this->seq.c_str() ); this->running = false; } bool Device::login() { NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY in = {0}; in.dwSize = sizeof in; strcpy(in.szIP, this->ip.c_str()); in.nPort = this->port; strcpy(in.szUserName, gConfLoginUser.c_str()); strcpy(in.szPassword, gConfLoginPass.c_str()); in.emSpecCap = EM_LOGIN_SPEC_CAP_TCP; NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY out; out.dwSize = sizeof out; for (int i = 0; i < 3; ++i) { this->loginId = CLIENT_LoginWithHighLevelSecurity(&in, &out); if (this->loginId) { Log(Trace, "device seq[%s] login success", this->seq.c_str()); usleep(1000000); return true; } sleep(1); } Log( Error, "device(ip[%s], mac[%s], seq[%s]) login fail", this->ip.c_str(), this->mac.c_str(), this->seq.c_str() ); this->running = false; return false; } void Device::logout() { if (this->loginId) CLIENT_Logout(this->loginId); this->loginId = 0, this->running = false; } bool Device::subscribe() { if (isFaceDevice) { this->subId = CLIENT_RealLoadPictureEx( this->loginId, 0, EVENT_IVS_ACCESS_CTL, TRUE, onSubscribeData, 0, nullptr ); } else { this->subId = CLIENT_RealLoadPictureEx( this->loginId, 0, EVENT_IVS_TRAFFICJUNCTION, TRUE, onSubscribeData, 0, nullptr ); } if (this->subId) { Log(Trace, "device seq[%s] subscribe success", this->seq.c_str()); return true; } Log( Error, "device(ip[%s], mac[%s], seq[%s]) face subscribe fail", this->ip.c_str(), this->mac.c_str(), this->seq.c_str() ); this->running = false; return false; } void Device::unsubscribe() { if (this->subId) CLIENT_StopLoadPic(this->subId); this->subId = 0, this->running = false; } void Device::varUserInsert(const User &user) { bool have = false; std::lock_guard lock(uMtx); for (const User &itr : faceUserList) { if (itr.uid == user.uid) { have = true; break; } } if (!have) faceUserList.push_back(user); } void Device::varUserDelete(const std::string &uid) { std::lock_guard lock(uMtx); for (auto it = faceUserList.begin(); it != faceUserList.end(); ++it) { if (it->uid == uid) { faceUserList.erase(it); break; } } } bool Device::varUserExists(const std::string &uid) { std::lock_guard lock(uMtx); for (User &user : faceUserList) if (user.uid == uid) return true; return false; } bool Device::addUserFace(const std::string &uid, const std::string &face, std::string &msg) { NET_IN_ADD_FACE_INFO in; in.dwSize = sizeof in; strcpy(in.szUserID, uid.c_str()); in.stuFaceInfo.nFacePhoto = 1; in.stuFaceInfo.nFacePhotoLen[0] = imgcpy(in.stuFaceInfo.pszFacePhoto[0], face); // Log(Info, "face-size: %ld, pho-len:%d", face.size(), in.stuFaceInfo.nFacePhotoLen[0]); // imageSave("./java.jpg", in.stuFaceInfo.pszFacePhoto[0], in.stuFaceInfo.nFacePhotoLen[0]); NET_OUT_ADD_FACE_INFO out; out.dwSize = sizeof out; bool res = CLIENT_FaceInfoOpreate(loginId, EM_FACEINFO_OPREATE_ADD, &in, &out, gWaitTime); if (!res) msg = "user face add failed"; delete[] in.stuFaceInfo.pszFacePhoto[0]; return res; } bool Device::removeUserOnly(const std::string &uid, std::string &msg) { NET_IN_ACCESS_USER_SERVICE_REMOVE in; in.dwSize = sizeof in; in.nUserNum = 1; std::strcpy(in.szUserID[0], uid.c_str()); in.bUserIDEx = 0; NET_OUT_ACCESS_USER_SERVICE_REMOVE out; out.dwSize = sizeof out; out.nMaxRetNum = 1; out.pFailCode = new NET_EM_FAILCODE; bool res = CLIENT_OperateAccessUserService( loginId, NET_EM_ACCESS_CTL_USER_SERVICE_REMOVE, &in, &out, gWaitTime ); if (res) varUserDelete(uid); else msg = "user info delete failed"; delete out.pFailCode; return res; } bool Device::removeUserFace(const std::string &uid, std::string &msg) { NET_IN_REMOVE_FACE_INFO in; in.dwSize = sizeof in; strcpy(in.szUserID, uid.c_str()); NET_OUT_REMOVE_FACE_INFO out; out.dwSize = sizeof out; bool res = CLIENT_FaceInfoOpreate(loginId, EM_FACEINFO_OPREATE_REMOVE, &in, &out, gWaitTime); if (!res) msg = "user face remove failed"; return res; } void Device::varCarWoBInsert(const bool &isBlack, const Plate &plate) { bool have = false; std::lock_guard lock(isBlack ? cbMtx : cwMtx); for (const Plate &itr : isBlack ? carBlackList : carWhiteList) { if (itr.cid == plate.cid) { have = true; break; } } if (!have) isBlack ? carBlackList.push_back(plate) : carWhiteList.push_back(plate); } void Device::varCarWoBDelete(const bool &isBlack, const int &cid) { std::lock_guard lock(isBlack ? cbMtx : cwMtx); for (auto it = (isBlack ? carBlackList : carWhiteList).begin(); it != (isBlack ? carBlackList : carWhiteList).end(); ++it) { if (it->cid == cid) { (isBlack ? carBlackList : carWhiteList).erase(it); break; } } } bool Device::varCarWoBExists(const bool &isBlack, const int &cid) { std::lock_guard lock(isBlack ? cbMtx : cwMtx); for (const Plate &plate : isBlack ? carBlackList : carWhiteList) if (plate.cid == cid) return true; return false; } bool Device::varCarWoBExists(const bool &isBlack, const std::string &plate) { std::lock_guard lock(isBlack ? cbMtx : cwMtx); for (const Plate &itr : isBlack ? carBlackList : carWhiteList) if (itr.plate == plate) return true; return false; } bool Device::insertOneCarWoBList(const bool &isBlack, Plate &plateInfo, std::string &msg) { if (varCarWoBExists(isBlack, plateInfo.plate)) { msg = "exist already"; return false; } NET_IN_OPERATE_TRAFFIC_LIST_RECORD in; in.dwSize = sizeof in; in.emOperateType = NET_TRAFFIC_LIST_INSERT; in.emRecordType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST; auto *info = new NET_INSERT_RECORD_INFO; info->dwSize = sizeof(NET_INSERT_RECORD_INFO); auto *record = new NET_TRAFFIC_LIST_RECORD; strcpy(record->szMasterOfCar, plateInfo.name.c_str()); strcpy(record->szPlateNumber, plateInfo.plate.c_str()); time_t tst = plateInfo.timestamp / 1000; struct tm *timeInfo = localtime(&tst); record->stCancelTime.dwYear = timeInfo->tm_year + 1900, record->stCancelTime.dwMonth = timeInfo->tm_mon + 1; record->stCancelTime.dwDay = timeInfo->tm_mday, record->stCancelTime.dwHour = timeInfo->tm_hour; record->stCancelTime.dwMinute = timeInfo->tm_min, record->stCancelTime.dwSecond = timeInfo->tm_sec; record->stBeginTime.dwYear = 2000, record->stBeginTime.dwMonth = 1, record->stBeginTime.dwDay = 1; record->stBeginTime.dwHour = 0, record->stBeginTime.dwMinute = 0, record->stBeginTime.dwSecond = 0; record->nAuthrityNum = 0; info->pRecordInfo = record; in.pstOpreateInfo = info; NET_OUT_OPERATE_TRAFFIC_LIST_RECORD out; out.dwSize = sizeof out; bool res = CLIENT_OperateTrafficList(loginId, &in, &out); if (res) { plateInfo.cid = out.nRecordNo; plateInfo.cid_s = std::to_string(out.nRecordNo); varCarWoBInsert(isBlack, plateInfo); } else { msg = "insert failed"; plateInfo.cid = 0; } delete record; delete info; return res; } bool Device::removeOneCarWoBList(const bool &isBlack, const int &cid, std::string &msg) { if (!varCarWoBExists(isBlack, cid)) { msg = "no such plate"; return false; } NET_IN_OPERATE_TRAFFIC_LIST_RECORD in; in.dwSize = sizeof in; in.emOperateType = NET_TRAFFIC_LIST_REMOVE; in.emRecordType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST; auto *info = new NET_REMOVE_RECORD_INFO; info->dwSize = sizeof(NET_REMOVE_RECORD_INFO); info->nRecordNo = cid; in.pstOpreateInfo = info; NET_OUT_OPERATE_TRAFFIC_LIST_RECORD out; out.dwSize = sizeof out; bool res = CLIENT_OperateTrafficList(loginId, &in, &out); if (res) varCarWoBDelete(isBlack, cid); else msg = "remove failed"; delete info; return res; } Plate *Device::getPlateByCNo(const std::string &cno) { for (auto &itr : carWhiteList) if (itr.plate == cno) return &itr; for (auto &itr : carBlackList) if (itr.plate == cno) return &itr; return nullptr; } } namespace hm { Device::Device(DEVICE_NET_INFO_EX2 *info) { this->inited = (info->stuDevInfo.byInitStatus & 3) != 1; this->port = info->stuDevInfo.nPort; this->reset = info->stuDevInfo.byPwdResetWay; this->seq = info->stuDevInfo.szSerialNo; this->mac = info->stuDevInfo.szMac; this->ip = info->stuDevInfo.szIP; this->local = info->szLocalIP; // 108: {szDeviceType: BSC, szDetailType: DH-ASI31A-MW, szNewDetailType: DH-ASI31A-MW} // 109: {szDeviceType: ITC, szDetailType: ITC313-PW2A-LF, szNewDetailType: ITC313-PW2A-LF} this->isFaceDevice = strcmp("DH-ASI31A-MW", info->stuDevInfo.szDetailType) == 0; this->online = this->running = false; this->loginId = this->subId = 0; } Device::~Device() { this->unsubscribe(); this->logout(); } void Device::queryFaceUsers() { NET_IN_USERINFO_START_FIND start_in; start_in.dwSize = sizeof start_in; strcpy(start_in.szUserID, ""); NET_OUT_USERINFO_START_FIND start_out; start_out.dwSize = sizeof start_out; LLONG handler = CLIENT_StartFindUserInfo(loginId, &start_in, &start_out, gWaitTime); if (handler) { int offset = 0, count = 10; faceUserList.clear(); while (offset < start_out.nTotalCount) { NET_IN_USERINFO_DO_FIND find_in; find_in.dwSize = sizeof find_in; find_in.nStartNo = offset; find_in.nCount = count; NET_OUT_USERINFO_DO_FIND find_out; find_out.dwSize = sizeof find_out; find_out.nMaxNum = count; find_out.pstuInfo = new NET_ACCESS_USER_INFO[count]; bool res = CLIENT_DoFindUserInfo(handler, &find_in, &find_out, gWaitTime); if (res) { for (int i = 0; i < find_out.nRetNum; ++i) { User one = { .uid=find_out.pstuInfo[i].szUserID, .name=find_out.pstuInfo[i].szName, .password = find_out.pstuInfo[i].szPsw, .timestamp=1000 * toTimestamp( find_out.pstuInfo[i].stuValidEndTime.dwYear, find_out.pstuInfo[i].stuValidEndTime.dwMonth, find_out.pstuInfo[i].stuValidEndTime.dwDay, find_out.pstuInfo[i].stuValidEndTime.dwHour, find_out.pstuInfo[i].stuValidEndTime.dwMinute, find_out.pstuInfo[i].stuValidEndTime.dwSecond ) }; varUserInsert(one); } offset += find_out.nRetNum; delete[] find_out.pstuInfo; } else break; } CLIENT_StopFindUserInfo(handler); } } void Device::queryCarWoBList(const bool &isBlack) { NET_IN_FIND_RECORD_PARAM find_in; find_in.dwSize = sizeof find_in; find_in.emType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST; auto *find_cond = new FIND_RECORD_TRAFFICREDLIST_CONDITION; find_cond->dwSize = sizeof(FIND_RECORD_TRAFFICREDLIST_CONDITION); strcpy(find_cond->szPlateNumber, ""); strcpy(find_cond->szPlateNumberVague, ""); find_cond->nQueryResultBegin = 0; find_cond->bRapidQuery = 0; find_in.pQueryCondition = find_cond; NET_OUT_FIND_RECORD_PARAM find_out; find_out.dwSize = sizeof find_out; bool res = CLIENT_FindRecord(loginId, &find_in, &find_out); if (res) { NET_IN_QUEYT_RECORD_COUNT_PARAM query_in; query_in.dwSize = sizeof query_in; query_in.lFindeHandle = find_out.lFindeHandle; NET_OUT_QUEYT_RECORD_COUNT_PARAM query_out; query_out.dwSize = sizeof query_out; res = CLIENT_QueryRecordCount(&query_in, &query_out); if (res) { int found = 0, batch = 5; while (found < query_out.nRecordCount) { NET_IN_FIND_NEXT_RECORD_PARAM do_in; do_in.dwSize = sizeof do_in; do_in.lFindeHandle = find_out.lFindeHandle; do_in.nFileCount = batch; NET_OUT_FIND_NEXT_RECORD_PARAM do_out; do_out.dwSize = sizeof do_out; do_out.nMaxRecordNum = batch; auto *records = new NET_TRAFFIC_LIST_RECORD[5]; do_out.pRecordList = records; for (int i = 0; i < batch; ++i) records[i].dwSize = sizeof(NET_TRAFFIC_LIST_RECORD); res = CLIENT_FindNextRecord(&do_in, &do_out); if (res) { found += do_out.nRetRecordNum; for (int i = 0; i < do_out.nRetRecordNum; ++i) { Plate one = { .name = records[i].szMasterOfCar, .plate = records[i].szPlateNumber, .cid_s = std::to_string(records[i].nRecordNo), .cid = records[i].nRecordNo, .timestamp = 1000 * toTimestamp( records[i].stCancelTime.dwYear, records[i].stCancelTime.dwMonth, records[i].stCancelTime.dwDay, records[i].stCancelTime.dwHour, records[i].stCancelTime.dwMinute, records[i].stCancelTime.dwSecond ) }; varCarWoBInsert(isBlack, one); } } else break; delete[] records; } } CLIENT_FindRecordClose(find_out.lFindeHandle); } delete find_cond; } void Device::Start() { if (this->running) return; this->running = true; if (!this->inited) this->init(); if (!this->login()) return; this->online = true; if (!this->subscribe()) return; } void Device::onAccessCtlEvent(DEV_EVENT_ACCESS_CTL_INFO *info, BYTE *imgBuf, DWORD bufSize) { char status[2] = {info->bStatus ? '1' : '0', 0}, method[64] = {0}, time[32] = {0}; strcpy(method, gOpenTypeMap[0].c_str()); if (gOpenTypeMap.find(info->emOpenMethod) != gOpenTypeMap.end()) strcpy(method, gOpenTypeMap[info->emOpenMethod].c_str()); sprintf( time, "%d-%02d-%02d %02d:%02d:%02d", info->UTC.dwYear, info->UTC.dwMonth, info->UTC.dwDay, info->UTC.dwHour + 8, info->UTC.dwMinute, info->UTC.dwSecond ); Log( Info, R"({"mac":"%s","seq":"%s","time":"%s","result":%s,"userId":"%s","userName":"%s","method":"%s"})", this->mac.c_str(), this->seq.c_str(), time, status, info->szUserID, info->szCardName, method ); // imageSave("./face.jpg", imgBuf, bufSize); std::map data{ {"mac", this->mac}, {"seq", this->seq}, {"time", time}, {"result", status}, {"userId", info->szUserID}, {"userName", info->szCardName}, {"method", method} }; dataUpload(gConfFaceRemote, data, imgBuf, bufSize); } void Device::onTrafficJunctionEvent(DEV_EVENT_TRAFFICJUNCTION_INFO *info, BYTE *imgBuf, DWORD bufSize) { char time[32] = {0}, speed[4] = {0}, status[2] = {info->byOpenStrobeState > 1 ? '1' : '0', 0}; sprintf(speed, "%d", info->nSpeed); sprintf( time, "%d-%02d-%02d %02d:%02d:%02d", info->UTC.dwYear, info->UTC.dwMonth, info->UTC.dwDay, info->UTC.dwHour, info->UTC.dwMinute, info->UTC.dwSecond ); std::string cno(info->stTrafficCar.szPlateNumber), username, cid; if (!cno.empty()) { Plate *plate = getPlateByCNo(cno); if (plate != nullptr) { username = plate->name; cid = plate->cid_s; } } Log( Info, 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"})", this->mac.c_str(), this->seq.c_str(), time, info->stTrafficCar.szPlateNumber, username.c_str(), cid.c_str(), info->stTrafficCar.szPlateType, info->stTrafficCar.szPlateColor, info->stuVehicle.szText, info->stuVehicle.szObjectSubType, info->stTrafficCar.szVehicleColor, speed, status ); // imageSave("./car.jpg", imgBuf, bufSize); std::map data{ {"mac", this->mac}, {"seq", this->seq}, {"time", time}, {"plateNumber", info->stTrafficCar.szPlateNumber}, {"username", username}, {"cid", cid}, {"plateType", info->stTrafficCar.szPlateType}, {"plateColor", info->stTrafficCar.szPlateColor}, {"carType", info->stuVehicle.szText}, {"carSubType", info->stuVehicle.szObjectSubType}, {"carColor", info->stTrafficCar.szVehicleColor}, {"speed", speed}, {"result", status}, }; dataUpload(gConfCarRemote, data, imgBuf, bufSize); } std::string Device::getJsonStr() { /* 1: online: 1 -> true, 0 -> false * 37: {"mac":"","seq":"","ip":"","online":} * */ size_t size = mac.size() + seq.size() + ip.size() + 38; std::string res(size, 0); sprintf( res.data(), R"({"mac":"%s","seq":"%s","ip":"%s","online":%d})", mac.c_str(), seq.c_str(), ip.c_str(), online ); return res; } bool Device::getFaceUsers(std::vector &users, std::string &msg) { for (User &user : faceUserList) users.push_back(user.getJsonStr()); return true; } bool Device::insertFaceUser(const User &user, std::string &msg) { if (varUserExists(user.uid)) { msg = "user existed already"; return false; } NET_IN_ACCESS_USER_SERVICE_INSERT in; in.dwSize = sizeof in; in.nInfoNum = 1; auto *usr = new NET_ACCESS_USER_INFO; usr->bUserIDEx = 0; strcpy(usr->szUserID, user.uid.c_str()); usr->bUseNameEx = 0; strcpy(usr->szName, user.name.c_str()); strcpy(usr->szPsw, user.password.c_str()); usr->emUserType = NET_ENUM_USER_TYPE_NORMAL; usr->nUserStatus = 0; usr->nDoorNum = 1, usr->nDoors[0] = 0; usr->nTimeSectionNum = 1, usr->nTimeSectionNo[0] = 255; usr->nSpecialDaysScheduleNum = 1, usr->nSpecialDaysSchedule[0] = 255; time_t tst = user.timestamp / 1000; struct tm *timeInfo = localtime(&tst); usr->stuValidEndTime.dwYear = timeInfo->tm_year + 1900; usr->stuValidEndTime.dwMonth = timeInfo->tm_mon + 1; usr->stuValidEndTime.dwDay = timeInfo->tm_mday; usr->stuValidEndTime.dwHour = timeInfo->tm_hour; usr->stuValidEndTime.dwMinute = timeInfo->tm_min; usr->stuValidEndTime.dwSecond = timeInfo->tm_sec; usr->stuValidBeginTime.dwYear = 2000; usr->stuValidBeginTime.dwMonth = 1; usr->stuValidBeginTime.dwDay = 1; usr->stuValidBeginTime.dwHour = 0; usr->stuValidBeginTime.dwMinute = 0; usr->stuValidBeginTime.dwSecond = 0; usr->nFirstEnterDoorsNum = 0; usr->emAuthority = NET_ATTENDANCE_AUTHORITY_CUSTOMER; usr->nFloorNum = 0; usr->nRoom = 0; usr->bFloorNoExValid = 0; usr->nFloorNumEx = 0; usr->bFloorNoEx2Valid = 0; usr->nUserTimeSectionsNum = 0; usr->bUserInfoExValid = 0; usr->bUserInfoEx2Valid = 0; in.pUserInfo = usr; NET_OUT_ACCESS_USER_SERVICE_INSERT out; out.dwSize = sizeof out; out.nMaxRetNum = 1; out.pFailCode = new NET_EM_FAILCODE; bool ok = true, res = CLIENT_OperateAccessUserService( loginId, NET_EM_ACCESS_CTL_USER_SERVICE_INSERT, &in, &out, gWaitTime ); if (res) { res = addUserFace(user.uid, user.face, msg); if (res) varUserInsert(user); else { ok = false; removeUserOnly(user.uid, msg); } } else { ok = false; msg = "usr info insert failed"; } delete usr; delete out.pFailCode; return ok; } bool Device::removeFaceUser(const std::string &uid, std::string &msg) { if (!varUserExists(uid)) { msg = "no such user"; return false; } bool ok1 = removeUserFace(uid, msg), ok2 = removeUserOnly(uid, msg); return ok1 && ok2; } bool Device::getCarWoBList(const bool &isBlack, std::vector &list, std::string &msg) { for (Plate &plate : isBlack ? carBlackList : carWhiteList) list.push_back(plate.getJsonStr()); return true; } bool Device::insertCarWoBList(const bool &isBlack, std::vector &list, std::string &msg) { json::Parser parser; json::Value result = parser.parse("[]"); for (Plate &info : list) { json::Value one = parser.parse("{}"); std::string reason; bool res = insertOneCarWoBList(isBlack, info, reason); one["cid"] = json::Value(info.cid); one["plate"] = json::Value(info.plate); one["success"] = json::Value(res); one["msg"] = json::Value(reason); result.push_back(one); } msg = result.str(); return true; } bool Device::removeCarWoBList(const bool &isBlack, const std::vector &cids, std::string &msg) { json::Parser parser; json::Value result = parser.parse("[]"); for (const int &cid : cids) { json::Value one = parser.parse("{}"); std::string reason; bool res = removeOneCarWoBList(isBlack, cid, reason); one["cid"] = json::Value(cid); one["success"] = json::Value(res); one["msg"] = json::Value(reason); result.push_back(one); } msg = result.str(); return true; } }