1.准备

门禁设备型号 DS-K1T671M
NVR设备型号 DS-7608N-K2


jar包需要引入到项目里,lib则是库文件

2.需求

在项目中集成海康门禁的刷脸记录,NVR视频回放列表

3.获取门禁刷脸记录代码


import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;/***  海康门禁* @author root*/public class Test2 {static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;static int lUserID = -1;//用户句柄static int m_lSetCardCfgHandle = -1; //下发卡长连接句柄static int m_lSetFaceCfgHandle = -1; //下发人脸长连接句柄static int dwState = -1; //下发卡数据状态static int dwFaceState = -1; //下发人脸数据状态static int lHandle = -1; //下发人脸数据状态static int lAlarmHandle = -1; //下发人脸数据状态static int iCharEncodeType = 0;//设备字符集public void login() {//注册HCNetSDK.NET_DVR_USER_LOGIN_INFO mStrLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息String m_sDeviceIP = "172.16.20.208";//设备ip地址mStrLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];System.arraycopy(m_sDeviceIP.getBytes(), 0, mStrLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());String m_sUsername = "admin";//设备用户名mStrLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];System.arraycopy(m_sUsername.getBytes(), 0, mStrLoginInfo.sUserName, 0, m_sUsername.length());String m_sPassword = "hk12345";//设备密码mStrLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];System.arraycopy(m_sPassword.getBytes(), 0, mStrLoginInfo.sPassword, 0, m_sPassword.length());mStrLoginInfo.wPort = 8000;mStrLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是mStrLoginInfo.write();HCNetSDK.NET_DVR_DEVICEINFO_V40 mStrDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息lUserID = hCNetSDK.NET_DVR_Login_V40(mStrLoginInfo, mStrDeviceInfo);if (lUserID == -1) {System.out.println("登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("登录成功!");iCharEncodeType = mStrDeviceInfo.byCharEncodeType;}}public void getOneCard(String strCardNo) {HCNetSDK.NET_DVR_CARD_COND struCardCond = new HCNetSDK.NET_DVR_CARD_COND();struCardCond.read();struCardCond.dwSize = struCardCond.size();struCardCond.dwCardNum = 1; //查询一个卡参数struCardCond.write();Pointer ptrStruCond = struCardCond.getPointer();m_lSetCardCfgHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_CARD, ptrStruCond, struCardCond.size(), null, null);if (m_lSetCardCfgHandle == -1) {System.out.println("建立查询卡参数长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立查询卡参数长连接成功!");}//查找指定卡号的参数,需要下发查找的卡号条件HCNetSDK.NET_DVR_CARD_SEND_DATA struCardNo = new HCNetSDK.NET_DVR_CARD_SEND_DATA();struCardNo.read();struCardNo.dwSize = struCardNo.size();for (int i = 0; i < HCNetSDK.ACS_CARD_NO_LEN; i++) {struCardNo.byCardNo[i] = 0;}for (int i = 0; i < strCardNo.length(); i++) {struCardNo.byCardNo[i] = strCardNo.getBytes()[i];}struCardNo.write();//用户记录HCNetSDK.NET_DVR_CARD_RECORD struCardRecord = new HCNetSDK.NET_DVR_CARD_RECORD();struCardRecord.read();HCNetSDK.NET_DVR_AUTH_INFO authInfo = new HCNetSDK.NET_DVR_AUTH_INFO();IntByReference pInt = new IntByReference(0);while (true) {dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetCardCfgHandle, struCardNo.getPointer(), struCardNo.size(),struCardRecord.getPointer(), struCardRecord.size(), pInt);struCardRecord.read();if (dwState == -1) {System.out.println("NET_DVR_SendWithRecvRemoteConfig查询卡参数调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {System.out.println("配置等待");try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {System.out.println("获取卡参数失败, 卡号: " + strCardNo);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {System.out.println("获取卡参数异常, 卡号: " + strCardNo);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {try {String strName = "";if ((iCharEncodeType == 0) || (iCharEncodeType == 1) || (iCharEncodeType == 2)) {strName = new String(struCardRecord.byName, "GBK").trim();}if (iCharEncodeType == 6) {strName = new String(struCardRecord.byName, StandardCharsets.UTF_8).trim();}System.out.println("获取卡参数成功, 卡号: " + new String(struCardRecord.byCardNo).trim()+ ", 卡类型:" + struCardRecord.byCardType+ ", 姓名:" + strName);} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {System.out.println("获取卡参数完成");break;}}if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("NET_DVR_StopRemoteConfig接口成功");}}public void setCartTemplate(int iPlanTemplateNumber) {int iErr = 0;//设置卡权限计划模板参数HCNetSDK.NET_DVR_PLAN_TEMPLATE_COND struPlanCond = new HCNetSDK.NET_DVR_PLAN_TEMPLATE_COND();struPlanCond.dwSize = struPlanCond.size();struPlanCond.dwPlanTemplateNumber = iPlanTemplateNumber;//计划模板编号,从1开始,最大值从门禁能力集获取struPlanCond.wLocalControllerID = 0;//就地控制器序号[1,64],0表示门禁主机struPlanCond.write();HCNetSDK.NET_DVR_PLAN_TEMPLATE struPlanTemCfg = new HCNetSDK.NET_DVR_PLAN_TEMPLATE();struPlanTemCfg.dwSize = struPlanTemCfg.size();struPlanTemCfg.byEnable = 1; //是否使能:0- 否,1- 是struPlanTemCfg.dwWeekPlanNo = 1;//周计划编号,0表示无效struPlanTemCfg.dwHolidayGroupNo[0] = 0;//假日组编号,按值表示,采用紧凑型排列,中间遇到0则后续无效byte[] byTemplateName;try {byTemplateName = "计划模板名称测试".getBytes("GBK");//计划模板名称for (int i = 0; i < HCNetSDK.NAME_LEN; i++) {struPlanTemCfg.byTemplateName[i] = 0;}System.arraycopy(byTemplateName, 0, struPlanTemCfg.byTemplateName, 0, byTemplateName.length);} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}struPlanTemCfg.write();IntByReference pInt = new IntByReference(0);Pointer lpStatusList = pInt.getPointer();if (!hCNetSDK.NET_DVR_SetDeviceConfig(lUserID, HCNetSDK.NET_DVR_SET_CARD_RIGHT_PLAN_TEMPLATE_V50, 1, struPlanCond.getPointer(), struPlanCond.size(), lpStatusList, struPlanTemCfg.getPointer(), struPlanTemCfg.size())) {iErr = hCNetSDK.NET_DVR_GetLastError();System.out.println("NET_DVR_SET_CARD_RIGHT_PLAN_TEMPLATE_V50失败,错误号:" + iErr);return;}System.out.println("NET_DVR_SET_CARD_RIGHT_PLAN_TEMPLATE_V50成功!");//获取卡权限周计划参数HCNetSDK.NET_DVR_WEEK_PLAN_COND struWeekPlanCond = new HCNetSDK.NET_DVR_WEEK_PLAN_COND();struWeekPlanCond.dwSize = struWeekPlanCond.size();struWeekPlanCond.dwWeekPlanNumber = 1;struWeekPlanCond.wLocalControllerID = 0;HCNetSDK.NET_DVR_WEEK_PLAN_CFG struWeekPlanCfg = new HCNetSDK.NET_DVR_WEEK_PLAN_CFG();struWeekPlanCond.write();struWeekPlanCfg.write();Pointer lpCond = struWeekPlanCond.getPointer();Pointer lpInbuferCfg = struWeekPlanCfg.getPointer();if (!hCNetSDK.NET_DVR_GetDeviceConfig(lUserID, HCNetSDK.NET_DVR_GET_CARD_RIGHT_WEEK_PLAN_V50, 1, lpCond, struWeekPlanCond.size(), lpStatusList, lpInbuferCfg, struWeekPlanCfg.size())) {iErr = hCNetSDK.NET_DVR_GetLastError();System.out.println("NET_DVR_GET_CARD_RIGHT_WEEK_PLAN_V50失败,错误号:" + iErr);return;}struWeekPlanCfg.read();struWeekPlanCfg.byEnable = 1; //是否使能:0- 否,1- 是//避免时间段交叉,先初始化for (int i = 0; i < 7; i++) {for (int j = 0; j < 8; j++) {struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].byEnable = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struBeginTime.byHour = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struBeginTime.byMinute = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struBeginTime.bySecond = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struEndTime.byHour = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struEndTime.byMinute = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[j].struTimeSegment.struEndTime.bySecond = 0;}}//一周7天,全天24小时for (int i = 0; i < 7; i++) {struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].byEnable = 1;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.byHour = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.byMinute = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.bySecond = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.byHour = 24;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.byMinute = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.bySecond = 0;}//一周7天,每天设置2个时间段/*for(int i=0;i<7;i++){struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].byEnable = 1;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.byHour = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.byMinute = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struBeginTime.bySecond = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.byHour = 11;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.byMinute = 59;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[0].struTimeSegment.struEndTime.bySecond = 59;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].byEnable = 1;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struBeginTime.byHour = 13;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struBeginTime.byMinute = 30;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struBeginTime.bySecond = 0;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struEndTime.byHour = 19;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struEndTime.byMinute = 59;struWeekPlanCfg.struPlanCfg[i].struPlanCfgDay[1].struTimeSegment.struEndTime.bySecond = 59;}*/struWeekPlanCfg.write();//设置卡权限周计划参数if (!hCNetSDK.NET_DVR_SetDeviceConfig(lUserID, HCNetSDK.NET_DVR_SET_CARD_RIGHT_WEEK_PLAN_V50, 1, lpCond, struWeekPlanCond.size(), lpStatusList, lpInbuferCfg, struWeekPlanCfg.size())) {iErr = hCNetSDK.NET_DVR_GetLastError();System.out.println("NET_DVR_SET_CARD_RIGHT_WEEK_PLAN_V50失败,错误号:" + iErr);return;}System.out.println("NET_DVR_SET_CARD_RIGHT_WEEK_PLAN_V50成功!");}public void getAllCard() {HCNetSDK.NET_DVR_CARD_COND struCardCond = new HCNetSDK.NET_DVR_CARD_COND();struCardCond.read();struCardCond.dwSize = struCardCond.size();struCardCond.dwCardNum = 0xffffffff; //查询所有struCardCond.write();Pointer ptrStruCond = struCardCond.getPointer();m_lSetCardCfgHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_CARD, ptrStruCond, struCardCond.size(), null, null);if (m_lSetCardCfgHandle == -1) {System.out.println("建立下发卡长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立下发卡长连接成功!");}HCNetSDK.NET_DVR_CARD_RECORD struCardRecord = new HCNetSDK.NET_DVR_CARD_RECORD();struCardRecord.read();struCardRecord.dwSize = struCardRecord.size();struCardRecord.write();IntByReference pInt = new IntByReference(0);while (true) {dwState = hCNetSDK.NET_DVR_GetNextRemoteConfig(m_lSetCardCfgHandle, struCardRecord.getPointer(), struCardRecord.size());struCardRecord.read();if (dwState == -1) {System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {System.out.println("配置等待");try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {System.out.println("获取卡参数失败");break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {System.out.println("获取卡参数异常");break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {try {String strName = "";if ((iCharEncodeType == 0) || (iCharEncodeType == 1) || (iCharEncodeType == 2)) {strName = new String(struCardRecord.byName, "GBK").trim();}if (iCharEncodeType == 6) {strName = new String(struCardRecord.byName, StandardCharsets.UTF_8).trim();}System.out.println("获取卡参数成功, 卡号: " + new String(struCardRecord.byCardNo).trim()+ ", 卡类型:" + struCardRecord.byCardType+ ", 姓名:" + strName);} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {System.out.println("获取卡参数完成");break;}}if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("NET_DVR_StopRemoteConfig接口成功");}}public void setOneCard(String strCardNo, short wPlanTemplateNumber) throws UnsupportedEncodingException, InterruptedException {HCNetSDK.NET_DVR_CARD_COND struCardCond = new HCNetSDK.NET_DVR_CARD_COND();struCardCond.read();struCardCond.dwSize = struCardCond.size();struCardCond.dwCardNum = 1;  //下发一张struCardCond.write();Pointer ptrStruCond = struCardCond.getPointer();m_lSetCardCfgHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_SET_CARD, ptrStruCond, struCardCond.size(), null, null);if (m_lSetCardCfgHandle == -1) {System.out.println("建立下发卡长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立下发卡长连接成功!");}HCNetSDK.NET_DVR_CARD_RECORD struCardRecord = new HCNetSDK.NET_DVR_CARD_RECORD();struCardRecord.read();struCardRecord.dwSize = struCardRecord.size();for (int i = 0; i < HCNetSDK.ACS_CARD_NO_LEN; i++) {struCardRecord.byCardNo[i] = 0;}for (int i = 0; i < strCardNo.length(); i++) {struCardRecord.byCardNo[i] = strCardNo.getBytes()[i];}struCardRecord.byCardType = 1; //普通卡struCardRecord.byLeaderCard = 0; //是否为首卡,0-否,1-是struCardRecord.byUserType = 0;struCardRecord.byDoorRight[0] = 1; //门1有权限struCardRecord.wCardRightPlan[0] = wPlanTemplateNumber;//关联门计划模板,使用了前面配置的计划模板struCardRecord.struValid.byEnable = 1;    //卡有效期使能,下面是卡有效期从2000-1-1 11:11:11到2030-1-1 11:11:11struCardRecord.struValid.struBeginTime.wYear = 2000;struCardRecord.struValid.struBeginTime.byMonth = 1;struCardRecord.struValid.struBeginTime.byDay = 1;struCardRecord.struValid.struBeginTime.byHour = 11;struCardRecord.struValid.struBeginTime.byMinute = 11;struCardRecord.struValid.struBeginTime.bySecond = 11;struCardRecord.struValid.struEndTime.wYear = 2030;struCardRecord.struValid.struEndTime.byMonth = 1;struCardRecord.struValid.struEndTime.byDay = 1;struCardRecord.struValid.struEndTime.byHour = 11;struCardRecord.struValid.struEndTime.byMinute = 11;struCardRecord.struValid.struEndTime.bySecond = 11;struCardRecord.dwEmployeeNo = 66611; //工号if ((iCharEncodeType == 0) || (iCharEncodeType == 1) || (iCharEncodeType == 2)) {byte[] strCardName = "赵六".getBytes("GBK");  //姓名for (int i = 0; i < HCNetSDK.NAME_LEN; i++) {struCardRecord.byName[i] = 0;}System.arraycopy(strCardName, 0, struCardRecord.byName, 0, strCardName.length);}if (iCharEncodeType == 6) {byte[] strCardName = "赵六".getBytes(StandardCharsets.UTF_8);  //姓名for (int i = 0; i < HCNetSDK.NAME_LEN; i++) {struCardRecord.byName[i] = 0;}System.arraycopy(strCardName, 0, struCardRecord.byName, 0, strCardName.length);}struCardRecord.write();HCNetSDK.NET_DVR_CARD_STATUS struCardStatus = new HCNetSDK.NET_DVR_CARD_STATUS();struCardStatus.read();struCardStatus.dwSize = struCardStatus.size();struCardStatus.write();IntByReference pInt = new IntByReference(0);while (true) {dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetCardCfgHandle, struCardRecord.getPointer(), struCardRecord.size(), struCardStatus.getPointer(), struCardStatus.size(), pInt);struCardStatus.read();if (dwState == -1) {System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {System.out.println("配置等待");Thread.sleep(10);} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {System.out.println("下发卡失败, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 错误码:" + struCardStatus.dwErrorCode);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {System.out.println("下发卡异常, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 错误码:" + struCardStatus.dwErrorCode);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {if (struCardStatus.dwErrorCode != 0) {System.out.println("下发卡成功,但是错误码" + struCardStatus.dwErrorCode + ", 卡号:" + new String(struCardStatus.byCardNo).trim());} else {System.out.println("下发卡成功, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 状态:" + struCardStatus.byStatus);}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {System.out.println("下发卡完成");break;}}if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("NET_DVR_StopRemoteConfig接口成功");}}public void setOneFace(String strCardNo) throws InterruptedException {HCNetSDK.NET_DVR_FACE_COND struFaceCond = new HCNetSDK.NET_DVR_FACE_COND();struFaceCond.read();struFaceCond.dwSize = struFaceCond.size();struFaceCond.byCardNo = "9654321".getBytes();struFaceCond.dwFaceNum = 1;  //下发一张struFaceCond.dwEnableReaderNo = 1;//人脸读卡器编号struFaceCond.write();Pointer ptrStruFaceCond = struFaceCond.getPointer();m_lSetFaceCfgHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_SET_FACE, ptrStruFaceCond, struFaceCond.size(), null, null);if (m_lSetFaceCfgHandle == -1) {System.out.println("建立下发人脸长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立下发人脸长连接成功!");}HCNetSDK.NET_DVR_FACE_RECORD struFaceRecord = new HCNetSDK.NET_DVR_FACE_RECORD();struFaceRecord.read();struFaceRecord.dwSize = struFaceRecord.size();for (int i = 0; i < HCNetSDK.ACS_CARD_NO_LEN; i++) {struFaceRecord.byCardNo[i] = 0;}for (int i = 0; i < strCardNo.length(); i++) {struFaceRecord.byCardNo[i] = strCardNo.getBytes()[i];}/****************************************** 从本地文件里面读取JPEG图片二进制数据*****************************************/FileInputStream picfile = null;int picdataLength = 0;try {picfile = new FileInputStream(new File(System.getProperty("user.dir") + ".\\lib\\face.jpg"));} catch (FileNotFoundException e) {e.printStackTrace();}try {picdataLength = picfile.available();} catch (IOException e1) {e1.printStackTrace();}if (picdataLength < 0) {System.out.println("input file dataSize < 0");return;}HCNetSDK.BYTE_ARRAY ptrpicByte = new HCNetSDK.BYTE_ARRAY(picdataLength);try {picfile.read(ptrpicByte.byValue);} catch (IOException e2) {e2.printStackTrace();}ptrpicByte.write();struFaceRecord.dwFaceLen = picdataLength;struFaceRecord.pFaceBuffer = ptrpicByte.getPointer();struFaceRecord.write();HCNetSDK.NET_DVR_FACE_STATUS struFaceStatus = new HCNetSDK.NET_DVR_FACE_STATUS();struFaceStatus.read();struFaceStatus.dwSize = struFaceStatus.size();struFaceStatus.write();IntByReference pInt = new IntByReference(0);while (true) {dwFaceState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetFaceCfgHandle, struFaceRecord.getPointer(), struFaceRecord.size(), struFaceStatus.getPointer(), struFaceStatus.size(), pInt);struFaceStatus.read();if (dwFaceState == -1) {System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwFaceState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {System.out.println("配置等待");Thread.sleep(10);} else if (dwFaceState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {System.out.println("下发人脸失败, 卡号: " + new String(struFaceStatus.byCardNo).trim() + ", 错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwFaceState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {System.out.println("下发卡异常, 卡号: " + new String(struFaceStatus.byCardNo).trim() + ", 错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwFaceState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {if (struFaceStatus.byRecvStatus != 1) {System.out.println("下发卡失败,人脸读卡器状态" + struFaceStatus.byRecvStatus + ", 卡号:" + new String(struFaceStatus.byCardNo).trim());break;} else {System.out.println("下发卡成功, 卡号: " + new String(struFaceStatus.byCardNo).trim() + ", 状态:" + struFaceStatus.byRecvStatus);}} else if (dwFaceState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {System.out.println("下发人脸完成");break;}}if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSetFaceCfgHandle)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("NET_DVR_StopRemoteConfig接口成功");}}public void delOneFace(String strCardNo) {HCNetSDK.NET_DVR_FACE_PARAM_CTRL struFaceDelCond = new HCNetSDK.NET_DVR_FACE_PARAM_CTRL();struFaceDelCond.dwSize = struFaceDelCond.size();struFaceDelCond.byMode = 0; //删除方式:0- 按卡号方式删除,1- 按读卡器删除struFaceDelCond.struProcessMode.setType(HCNetSDK.NET_DVR_FACE_PARAM_BYCARD.class);//需要删除人脸关联的卡号for (int i = 0; i < HCNetSDK.ACS_CARD_NO_LEN; i++) {struFaceDelCond.struProcessMode.struByCard.byCardNo[i] = 0;}System.arraycopy(strCardNo.getBytes(), 0, struFaceDelCond.struProcessMode.struByCard.byCardNo, 0, strCardNo.length());struFaceDelCond.struProcessMode.struByCard.byEnableCardReader[0] = 1; //读卡器struFaceDelCond.struProcessMode.struByCard.byFaceID[0] = 1; //人脸IDstruFaceDelCond.write();Pointer ptrFaceDelCond = struFaceDelCond.getPointer();boolean bRet = hCNetSDK.NET_DVR_RemoteControl(lUserID, HCNetSDK.NET_DVR_DEL_FACE_PARAM_CFG, ptrFaceDelCond, struFaceDelCond.size());if (!bRet) {System.out.println("删除人脸失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("删除人脸成功!");}}public void DelOneCard(String strCardNo) throws InterruptedException {HCNetSDK.NET_DVR_CARD_COND struCardCond = new HCNetSDK.NET_DVR_CARD_COND();struCardCond.read();struCardCond.dwSize = struCardCond.size();struCardCond.dwCardNum = 1;  //下发一张struCardCond.write();Pointer ptrStruCond = struCardCond.getPointer();m_lSetCardCfgHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_DEL_CARD, ptrStruCond, struCardCond.size(), null, null);if (m_lSetCardCfgHandle == -1) {System.out.println("建立删除卡长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立删除卡长连接成功!");}HCNetSDK.NET_DVR_CARD_SEND_DATA struCardData = new HCNetSDK.NET_DVR_CARD_SEND_DATA();struCardData.read();struCardData.dwSize = struCardData.size();for (int i = 0; i < HCNetSDK.ACS_CARD_NO_LEN; i++) {struCardData.byCardNo[i] = 0;}for (int i = 0; i < strCardNo.length(); i++) {struCardData.byCardNo[i] = strCardNo.getBytes()[i];}struCardData.write();HCNetSDK.NET_DVR_CARD_STATUS struCardStatus = new HCNetSDK.NET_DVR_CARD_STATUS();struCardStatus.read();struCardStatus.dwSize = struCardStatus.size();struCardStatus.write();IntByReference pInt = new IntByReference(0);while (true) {dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetCardCfgHandle, struCardData.getPointer(), struCardData.size(), struCardStatus.getPointer(), struCardStatus.size(), pInt);struCardStatus.read();if (dwState == -1) {System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {System.out.println("配置等待");Thread.sleep(10);} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {System.out.println("删除卡失败, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 错误码:" + struCardStatus.dwErrorCode);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {System.out.println("删除卡异常, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 错误码:" + struCardStatus.dwErrorCode);break;} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {if (struCardStatus.dwErrorCode != 0) {System.out.println("删除卡成功,但是错误码" + struCardStatus.dwErrorCode + ", 卡号:" + new String(struCardStatus.byCardNo).trim());} else {System.out.println("删除卡成功, 卡号: " + new String(struCardStatus.byCardNo).trim() + ", 状态:" + struCardStatus.byStatus);}} else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {System.out.println("删除卡完成");break;}}if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else {System.out.println("NET_DVR_StopRemoteConfig接口成功");}}/*** 调用设备事件*/public void getDeviceCase() {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");Date startTime = null;Date endTime = null;try {startTime = sdf.parse("20200609000000");   //开始时间endTime = sdf.parse("20200622220000");      //结束时间} catch (ParseException e) {e.printStackTrace();}List<Map<String, String>> eventList = new ArrayList<>();Map<String, String> eventMap = new HashMap<>();// 储存事件信息的map// 调用获取设备事件长连接HCNetSDK.NET_DVR_ACS_EVENT_COND struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();struAcsEventCond.read();struAcsEventCond.dwSize = struAcsEventCond.size();struAcsEventCond.dwMajor = 5;// 5代表event事件struAcsEventCond.dwMinor = 0x4b;// 代表刷脸成功struAcsEventCond.struStartTime = getHkTime(startTime);// ****必须要struAcsEventCond.struEndTime = getHkTime(endTime);// ***必须要struAcsEventCond.write();Pointer ptrStruEventCond = struAcsEventCond.getPointer();lHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_ACS_EVENT, ptrStruEventCond, struAcsEventCond.size(), null, null);if (lHandle == -1) {System.out.println("建立获取设备事件长连接失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());return;} else {System.out.println("建立获取设备事件连接成功!" + lHandle);}// 获取设备详细事件开始HCNetSDK.NET_DVR_ACS_EVENT_CFG struEventCFG = new HCNetSDK.NET_DVR_ACS_EVENT_CFG();struEventCFG.read();struEventCFG.dwSize = struEventCFG.size();struEventCFG.write();while (true) {dwState = hCNetSDK.NET_DVR_GetNextRemoteConfig(lHandle, struEventCFG.getPointer(), struEventCFG.size());struEventCFG.read();if (dwState == -1) {System.out.println("NET_DVR_GetNextRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());} else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {// 配置等待System.out.println("==========配置等待==============");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}} else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {// 获取事件失败System.out.println("===============获取设备事件失败=======================");break;} else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_EXCEPTION) {// 获取事件异常System.out.println("===============获取设备事件异常=======================");break;} else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {// 获取设备事件成功eventMap = new HashMap<>(16);eventMap.put("employeeNo", new String(struEventCFG.struAcsEventInfo.byEmployeeNo, StandardCharsets.UTF_8).trim());System.out.println("employeeNo:" + new String(struEventCFG.struAcsEventInfo.byEmployeeNo, StandardCharsets.UTF_8).trim());eventMap.put("cardNo", new String(struEventCFG.struAcsEventInfo.byCardNo, StandardCharsets.UTF_8).trim());System.out.println("cardNo:" + new String(struEventCFG.struAcsEventInfo.byCardNo, StandardCharsets.UTF_8).trim());eventMap.put("struTime", struEventCFG.struTime.toString());HCNetSDK.NET_DVR_TIME struTime = struEventCFG.struTime;System.out.println("struTime:" + struTime.dwYear + struTime.dwMonth + struTime.dwDay + struTime.dwHour + struTime.dwMinute + struTime.dwSecond);System.out.println("-------------------------------------------------");eventList.add(eventMap);} else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FINISH) {// 获取设备事件信息完成System.out.println("=============获取设备事件完成================");break;}}}//时间格式转换public static HCNetSDK.NET_DVR_TIME getHkTime(Date time) {HCNetSDK.NET_DVR_TIME structTime = new HCNetSDK.NET_DVR_TIME();String str = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(time);String[] times = str.split("-");structTime.dwYear = Integer.parseInt(times[0]);structTime.dwMonth = Integer.parseInt(times[1]);structTime.dwDay = Integer.parseInt(times[2]);structTime.dwHour = Integer.parseInt(times[3]);structTime.dwMinute = Integer.parseInt(times[4]);structTime.dwSecond = Integer.parseInt(times[5]);return structTime;}public static void main(String[] args) throws InterruptedException {Test2 test = new Test2();hCNetSDK.NET_DVR_Init();test.login();                //登陆Thread.sleep(500);//查询所有卡参数test.getAllCard();//查询刷脸记录test.getDeviceCase();//        test.SetCartTemplate(1); //计划模板配置
//        Thread.sleep(500);//        test.getAllLog();
//
//        String strCardNo = "1234569";
//        test.SetOneCard(strCardNo, (short) 1);    //下发1张卡号,关联计划模板1//        Thread.sleep(500);
//        test.GetOneCard(strCardNo); //查询指定卡参数
//
//        Thread.sleep(500);
//        test.SetOneFace(strCardNo);    //下发1张人脸//        Thread.sleep(5000);
//
//        test.DelOneFace(strCardNo);  //删除人脸
//        Thread.sleep(1000);
//        test.DelOneCard(strCardNo);  //删除卡号}
}

输出结果:

有些代码虽然没有用,但是还是有一定的参考意义

5.获取NVR视频回放列表


import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** 海康 NVR* @author root*/
public class Test3 {private static HCNetSDK hcNetSDK = HCNetSDK.INSTANCE;private int userId = -1;//用户句柄private int loadHandle = -1;//下载句柄static int lHandle = -1; //查找录像数据状态static int dwState = -1; //获取文件数据状态public void findVideoFiles (Date startTime, Date endTime, int channel){boolean initFlag = hcNetSDK.NET_DVR_Init();if (!initFlag) { //返回值为布尔值 fasle初始化失败System.out.println("海康sdk初始化失败!");}HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();String ip = "172.16.20.20";short port = 8000;String name = "admin";String password = "hk12345";userId = hcNetSDK.NET_DVR_Login_V30(ip, port, name, password, deviceInfo);if (userId == -1) {System.out.println("海康sdk登录失败!");}HCNetSDK.NET_DVR_FILECOND dvrFilecond = new HCNetSDK.NET_DVR_FILECOND();dvrFilecond.read();dvrFilecond.lChannel = channel;dvrFilecond.dwFileType = 0xff;dvrFilecond.dwIsLocked = 0xff;dvrFilecond.struStartTime = getHkTime(startTime);dvrFilecond.struStopTime = getHkTime(endTime);dvrFilecond.write();//查找录像文件lHandle = hcNetSDK.NET_DVR_FindFile_V30(userId, dvrFilecond);HCNetSDK.NET_DVR_FINDDATA_V30 dvrFinddataV30 = new HCNetSDK.NET_DVR_FINDDATA_V30();dvrFinddataV30.read();dvrFinddataV30.dwFileSize = dvrFinddataV30.size();dvrFinddataV30.write();while (true) {//获取文件信息dwState = hcNetSDK.NET_DVR_FindNextFile_V30(lHandle, dvrFinddataV30);dvrFinddataV30.read();if (dwState == -1) {System.out.println("NET_DVR_GetNextRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());} else if (dwState == HCNetSDK.NET_DVR_ISFINDING) {// 配置等待System.out.println("==========正在查找文件,请等待==============");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}} else if (dwState == HCNetSDK.NET_DVR_FILE_EXCEPTION) {// 获取事件异常System.out.println("===============查找文件时异常=======================");break;} else if (dwState == HCNetSDK.NET_DVR_FILE_SUCCESS) {String fileName = new String(dvrFinddataV30.sFileName, StandardCharsets.UTF_8).trim();System.out.println("文件名:" + fileName);HCNetSDK.NET_DVR_TIME struStartTime = dvrFinddataV30.struStartTime;String strStartTime = judgeSingleDigit(struStartTime.dwYear) +judgeSingleDigit(struStartTime.dwMonth) +judgeSingleDigit(struStartTime.dwDay) +judgeSingleDigit(struStartTime.dwHour) +judgeSingleDigit(struStartTime.dwMinute) +judgeSingleDigit(struStartTime.dwSecond);System.out.println("文件开始时间:" +  strStartTime);HCNetSDK.NET_DVR_TIME struStopTime = dvrFinddataV30.struStopTime;String strStopTime = judgeSingleDigit(struStopTime.dwYear) +judgeSingleDigit(struStopTime.dwMonth) +judgeSingleDigit(struStopTime.dwDay) +judgeSingleDigit(struStopTime.dwHour) +judgeSingleDigit(struStopTime.dwMinute) +judgeSingleDigit(struStopTime.dwSecond);System.out.println("文件开始时间:" + strStopTime);} else if (dwState == HCNetSDK.NET_DVR_NOMOREFILE) {// 获取设备事件信息完成System.out.println("=============没有更多的文件,查找结束================");break;}}}/*** 获取海康录像机格式的时间* @param time* @return*/private HCNetSDK.NET_DVR_TIME getHkTime(Date time) {HCNetSDK.NET_DVR_TIME structTime = new HCNetSDK.NET_DVR_TIME();String str = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(time);String[] times = str.split("-");structTime.dwYear = Integer.parseInt(times[0]);structTime.dwMonth = Integer.parseInt(times[1]);structTime.dwDay = Integer.parseInt(times[2]);structTime.dwHour = Integer.parseInt(times[3]);structTime.dwMinute =Integer.parseInt(times[4]);structTime.dwSecond = Integer.parseInt(times[5]);return structTime;}private static String judgeSingleDigit(int digit) {int length = (digit + "").length();if (digit < 10 && length == 1) {return "0" + digit;}return String.valueOf(digit);}public static void main(String[] args) throws UnsupportedEncodingException {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");Date startTime =null;Date endTime = null;try {startTime = sdf.parse("20200623000000");   //开始时间endTime =   sdf.parse("20200623100000");      //结束时间} catch (ParseException e) {e.printStackTrace();}Test3 test = new Test3();//回放通道33开始int channel = 33;test.findVideoFiles(startTime, endTime , channel);}
}

输出结果:

6.注意事项

7.后记

遇到的坑还是挺多的,海康接口文档有些方法HCNetSDK.java里没有。如果使用我这demo,建议使用我这份HCNetSDK.java

项目地址
https://gitee.com/youyu0307/hk_demo.git

写的不好见谅一下,有什么问题可以留言一起交流

Java项目集成海康威视门禁,NVR相关推荐

  1. 有做过海康威视门禁对接的么?java版本的

    有做过海康威视门禁对接的么?java版本的 求问怎么获取刷脸人的信息和设备信息.

  2. 【智能门禁系统设计】——项目需求分析(门禁终端软件)

    0.前言 门禁终端程序是运行在开发板上的程序,所以功能较少. 1.软件结构图 门禁终端软件:门禁终端软件主要使用QT+OpenCV实现,主要的功能就是提供密码.人脸.IC卡识别界面,然后根据用户输入的 ...

  3. Java项目集成apollo,SpringBoot集成Apollo配置中心

    准备工作 本文假设读者已经在本地部署Apollo配置中心,如还未部署可参考之前的文章 <Docker部署Apollo配置中心> 文章将引导在Docker中运行Apollo配置中心.在开始使 ...

  4. java项目集成谷歌登录验证器,给网站添加谷歌验证(我不是机器人)

    1.去谷歌网站.(如果没有谷歌gmail,也许还要注册gmail并登陆) 2.注册要验证的网站. Label中随意填写个标签. 'Choose the type of reCAPTCHA'中选择验证类 ...

  5. Java项目集成grafana_grafana 批量添加图表

    利用grafana做监控展示特别方便,而且界面还很有科技感,一般的使用都是自己手动添加图表,或者使用别人提供好的模板. 在一种情况下就比较尴尬了,我有100个实例的内存数据想展示,如果都放在一个tab ...

  6. 润乾V5与Java项目集成开发(1)

    1.安装润乾V5报表 2.进入安装目录D:\raqsoft\report5\web\webapps\demo,复制除web-inf文件夹外所有文件及文件夹 3.粘贴到项目webapp下 4.进入web ...

  7. java项目集成mybatis_JAVA应用程序单独集成Mybatis使用Demo

    参考博客:http://www.cnblogs.com/magialmoon/archive/2013/10/30/3397828.html 整体结构 POM依赖 org.mybatis mybati ...

  8. 门禁系统 java源代码_Java经典源码 门禁系统完整代码

    [实例简介] Java经典源码 门禁系统完整代码 门禁系统 另一种写法,代码和前一个系统有区别 [实例截图] [核心代码] ControlSys1 └── ControlSys1 ├── accp.l ...

  9. 51单片机项目之OLED显示多功能门禁系统(密码、刷卡、指纹、WIFI、蓝牙等)(一)硬件设计

    多功能门禁系统硬件设计 今天分享一款能够由个人独立完成的个人项目多功能门禁系统,具有以下功能: (1)指纹 1.指纹识别控制继电器开关电磁锁 2.添加指纹 3.删除指纹 (2)刷卡 1.RFID RC ...

  10. 智能卡门禁管理系统_综合门禁管理信息系统相关技术及未来准备

    综合门禁管理信息系统相关技术及未来准备 1)智能卡 基于我们对智能卡的认识,属于物联网的感应层,即实体所关联的感应媒介.从人的角度看,可能是卡(可能多张),也可能是密码.指纹.条码等:未来可能包括资产 ...

最新文章

  1. win7查看电脑上openCV的版本
  2. 理解int的存储方式以及VS二进制编辑器的使用
  3. 工具资源系列之给mac装个虚拟机
  4. 记录几款比较好用的jquery插件
  5. php显示doc文件乱码,如何解决php doc 乱码问题
  6. OpenSSL windows 下编译
  7. Python数据结构与算法(1.5)——Python基础之函数与异常
  8. 统一配置管理工具confd
  9. matlab遗传算法输出参数太多,用遗传算法工具箱时错误提示太多输出参数?
  10. 使用中值滤波器对图像降噪
  11. nginx参数keepalive_timeout
  12. iOS 15 更新,图标改版
  13. android iCloud 短信,云助手 基于安卓的iCloud
  14. HH的项链(树状数组)区间内不同的数量
  15. HTML小游戏18 —— html5版街头霸王游戏(附完整源码)
  16. 持续集成在Hexo自动化部署上的实践
  17. 【烈日炎炎战后端】JAVA集合(1.8万字)
  18. 几种软件开发方法对比
  19. C++排序——奖学金
  20. Android自定义注解不被混淆,Android 混淆压缩开启以及自定义混淆规则

热门文章

  1. Adobe Photoshop CC 2014 15.2.1 32/64位中文特别安装版+绿色版
  2. python中xlsxwriter模块_python xlsxwriter模块的使用
  3. c++win32项目 如何显示后再删除一个绘图_【AutoCAD】AutoCAD绘图软件优化的方法,提高启动速度,防止ACAD意外崩溃...
  4. osgEarth基础入门
  5. nodejs实现单点登录系统
  6. sso单点登录系统(精华篇)
  7. janusgraph 引入 java,janusgraph 默认server使用手记
  8. 微信小程序 - 方法
  9. tekla二次开发用C语言,Tekla二次开发怎么弄?一篇文章入门tekla二次开发!
  10. Latex 求职简历模版