1、下载大华官方设备网络sdk_java64,地址:https://www.dahuatech.com/service/downloadlists/836.html
2、sdk里面有例子,尽量使用大华封装好的东西,获取门禁卡记录用到了如下java类:
com/netsdk/lib
NetSDKLib.java
ToolKits.java
Utils.java
com/netsdk/demo/module
LoginModule.java
本以为com.netsdk.demo.module.GateModule.java里面会有现成的获取门禁刷卡记录的实现方法,可惜没有。比葫芦画瓢,自己写了一个。
3、在自己的spring boot项目中引入libs/jna.jar。
com/netsdk/lib
NetSDKLib.java
ToolKits.java
Utils.java
com/netsdk/demo/module
LoginModule.java
本以为com.netsdk.demo.module.GateModule.java里面会有现成的获取门禁刷卡记录的实现方法,可惜没有。比葫芦画瓢,自己写了一个。
3、在自己的spring boot项目中引入libs/jna.jar。
<dependency>
<groupId>com.dahua</groupId>
<artifactId>jna</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jna.jar</systemPath>
</dependency>
<groupId>com.dahua</groupId>
<artifactId>jna</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jna.jar</systemPath>
</dependency>
libs/win64下的dll文件是大华的类库,运行时要读取,在Utils.java中有读取的方法,
可以按照里面的路径存放于自己项目对应的路径。我的是spring boot项目,就把libs放在了启动工程的src文件夹的同级文件夹。
len-web
-src
-libs
-win64
可以按照里面的路径存放于自己项目对应的路径。我的是spring boot项目,就把libs放在了启动工程的src文件夹的同级文件夹。
len-web
-src
-libs
-win64
4、大华的坑:文档和类的注释中,都写明可以通过时间段来检索门禁刷卡记录,但是有的门禁设备不支持,只会把所有记录全都给你;
注意LoginModule中的初始化方法init,对于javaweb项目来讲,在服务启动时,初始化一次就行了,后面直接调用登录、登出方法即可,
千万不要多次调用init方法,这样java内存会爆掉,我开始就是这样干的(郁闷)……还有就是刷卡记录的时间不是北京时间,而是0时区
时间,所以获取到以后要加8个小时才是北京时间。
注意LoginModule中的初始化方法init,对于javaweb项目来讲,在服务启动时,初始化一次就行了,后面直接调用登录、登出方法即可,
千万不要多次调用init方法,这样java内存会爆掉,我开始就是这样干的(郁闷)……还有就是刷卡记录的时间不是北京时间,而是0时区
时间,所以获取到以后要加8个小时才是北京时间。
5、用maven打包时,如果漏掉了jna.jar,就在pom.xml中的spring-boot-maven-plugin加上<includeSystemScope>true</includeSystemScope>
内容如下:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
内容如下:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
6、GateModule.java代码
package com.dahua.module;
import com.dahua.lib.NetSDKLib;
import com.dahua.lib.ToolKits;
import com.sun.jna.Memory;
import com.dahua.lib.ToolKits;
import com.sun.jna.Memory;
public class GateModule {
/**
* 查询刷卡记录,获取查询句柄
* @param findCondition 查询条件
* @return
*/
public static NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] findRecords(NetSDKLib.NET_TIME startTime, NetSDKLib.NET_TIME endTime) {
// 接口入参
NetSDKLib.FIND_RECORD_ACCESSCTLCARDREC_CONDITION_EX findCondition = new NetSDKLib.FIND_RECORD_ACCESSCTLCARDREC_CONDITION_EX();
findCondition.bCardNoEnable = 0;
findCondition.stStartTime = startTime;
findCondition.stEndTime = endTime;
// CLIENT_FindRecord 接口入参
NetSDKLib.NET_IN_FIND_RECORD_PARAM stIn = new NetSDKLib.NET_IN_FIND_RECORD_PARAM();
stIn.emType = NetSDKLib.EM_NET_RECORD_TYPE.NET_RECORD_ACCESSCTLCARDREC_EX;
stIn.pQueryCondition = findCondition.getPointer();
// CLIENT_FindRecord 接口出参
NetSDKLib.NET_OUT_FIND_RECORD_PARAM stOut = new NetSDKLib.NET_OUT_FIND_RECORD_PARAM();
/**
* 查询刷卡记录,获取查询句柄
* @param findCondition 查询条件
* @return
*/
public static NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] findRecords(NetSDKLib.NET_TIME startTime, NetSDKLib.NET_TIME endTime) {
// 接口入参
NetSDKLib.FIND_RECORD_ACCESSCTLCARDREC_CONDITION_EX findCondition = new NetSDKLib.FIND_RECORD_ACCESSCTLCARDREC_CONDITION_EX();
findCondition.bCardNoEnable = 0;
findCondition.stStartTime = startTime;
findCondition.stEndTime = endTime;
// CLIENT_FindRecord 接口入参
NetSDKLib.NET_IN_FIND_RECORD_PARAM stIn = new NetSDKLib.NET_IN_FIND_RECORD_PARAM();
stIn.emType = NetSDKLib.EM_NET_RECORD_TYPE.NET_RECORD_ACCESSCTLCARDREC_EX;
stIn.pQueryCondition = findCondition.getPointer();
// CLIENT_FindRecord 接口出参
NetSDKLib.NET_OUT_FIND_RECORD_PARAM stOut = new NetSDKLib.NET_OUT_FIND_RECORD_PARAM();
findCondition.write();
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] pstRecordEx = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[0];
// 获取查询句柄
if(LoginModule.netsdk.CLIENT_FindRecord(LoginModule.m_hLoginHandle, stIn, stOut, 5000)) {
findCondition.read();
// 用于申请内存,假定2000次刷卡记录
int nFindCount = 2000;
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] pstRecord = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[nFindCount];
for(int i = 0; i < nFindCount; i++) {
pstRecord[i] = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC();
}
NetSDKLib.NET_IN_FIND_NEXT_RECORD_PARAM stNextIn = new NetSDKLib.NET_IN_FIND_NEXT_RECORD_PARAM();
stNextIn.lFindeHandle = stOut.lFindeHandle;
stNextIn.nFileCount = nFindCount;
NetSDKLib.NET_OUT_FIND_NEXT_RECORD_PARAM stNextOut = new NetSDKLib.NET_OUT_FIND_NEXT_RECORD_PARAM();
stNextOut.nMaxRecordNum = nFindCount;
// 申请内存
stNextOut.pRecordList = new Memory(pstRecord[0].dwSize * nFindCount);
stNextOut.pRecordList.clear(pstRecord[0].dwSize * nFindCount);
// 将数组内存拷贝给指针
ToolKits.SetStructArrToPointerData(pstRecord, stNextOut.pRecordList);
if(LoginModule.netsdk.CLIENT_FindNextRecord(stNextIn, stNextOut, 5000)) {
if(stNextOut.nRetRecordNum == 0) {
return pstRecordEx;
}
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] pstRecordEx = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[0];
// 获取查询句柄
if(LoginModule.netsdk.CLIENT_FindRecord(LoginModule.m_hLoginHandle, stIn, stOut, 5000)) {
findCondition.read();
// 用于申请内存,假定2000次刷卡记录
int nFindCount = 2000;
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] pstRecord = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[nFindCount];
for(int i = 0; i < nFindCount; i++) {
pstRecord[i] = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC();
}
NetSDKLib.NET_IN_FIND_NEXT_RECORD_PARAM stNextIn = new NetSDKLib.NET_IN_FIND_NEXT_RECORD_PARAM();
stNextIn.lFindeHandle = stOut.lFindeHandle;
stNextIn.nFileCount = nFindCount;
NetSDKLib.NET_OUT_FIND_NEXT_RECORD_PARAM stNextOut = new NetSDKLib.NET_OUT_FIND_NEXT_RECORD_PARAM();
stNextOut.nMaxRecordNum = nFindCount;
// 申请内存
stNextOut.pRecordList = new Memory(pstRecord[0].dwSize * nFindCount);
stNextOut.pRecordList.clear(pstRecord[0].dwSize * nFindCount);
// 将数组内存拷贝给指针
ToolKits.SetStructArrToPointerData(pstRecord, stNextOut.pRecordList);
if(LoginModule.netsdk.CLIENT_FindNextRecord(stNextIn, stNextOut, 5000)) {
if(stNextOut.nRetRecordNum == 0) {
return pstRecordEx;
}
// 获取卡信息
ToolKits.GetPointerDataToStructArr(stNextOut.pRecordList, pstRecord);
// 获取有用的信息
pstRecordEx = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[stNextOut.nRetRecordNum];
for(int i = 0; i < stNextOut.nRetRecordNum; i++) {
pstRecordEx[i] = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC();
pstRecordEx[i] = pstRecord[i];
}
}
LoginModule.netsdk.CLIENT_FindRecordClose(stOut.lFindeHandle);
}
return pstRecordEx;
}
}
ToolKits.GetPointerDataToStructArr(stNextOut.pRecordList, pstRecord);
// 获取有用的信息
pstRecordEx = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[stNextOut.nRetRecordNum];
for(int i = 0; i < stNextOut.nRetRecordNum; i++) {
pstRecordEx[i] = new NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC();
pstRecordEx[i] = pstRecord[i];
}
}
LoginModule.netsdk.CLIENT_FindRecordClose(stOut.lFindeHandle);
}
return pstRecordEx;
}
}
7、调用方式
boolean flag = LoginModule.login(hall.getGateIp(), 37777, "admin", "123456");
if (flag) {
// 检索结束时间:当前时间
Date endDateTime = calendar.getTime();
NetSDKLib.NET_TIME endTime = new NetSDKLib.NET_TIME();
endTime.setTime(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
// 获取检索开始时间:当前时间 - 5分钟
calendar.add(Calendar.MINUTE, -5);
Date startDateTime = calendar.getTime();
NetSDKLib.NET_TIME startTime = new NetSDKLib.NET_TIME();
startTime.setTime(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] cardRecords = GateModule.findRecords(startTime, endTime);
for (NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC cardRecord : cardRecords) {
// 卡号
String cardNo = new String(cardRecord.szCardNo).trim();
// 如果刷卡状态不正确,或者是按键开门,就不录入数据
if (cardRecord.bStatus != 1 || "00000000".equals(cardNo)) {
continue;
}
// 刷卡时间 转换为北京时间 +8小时
Date stuTime = DateUtil.convertStringToDate(cardRecord.stuTime.toStringTimeEx(), "yyyy-MM-dd HH:mm:ss");
Calendar stuCalendar = DateUtil.getCalendar(stuTime);
stuCalendar.add(Calendar.HOUR, 8);
}
}
boolean flag = LoginModule.login(hall.getGateIp(), 37777, "admin", "123456");
if (flag) {
// 检索结束时间:当前时间
Date endDateTime = calendar.getTime();
NetSDKLib.NET_TIME endTime = new NetSDKLib.NET_TIME();
endTime.setTime(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
// 获取检索开始时间:当前时间 - 5分钟
calendar.add(Calendar.MINUTE, -5);
Date startDateTime = calendar.getTime();
NetSDKLib.NET_TIME startTime = new NetSDKLib.NET_TIME();
startTime.setTime(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC[] cardRecords = GateModule.findRecords(startTime, endTime);
for (NetSDKLib.NET_RECORDSET_ACCESS_CTL_CARDREC cardRecord : cardRecords) {
// 卡号
String cardNo = new String(cardRecord.szCardNo).trim();
// 如果刷卡状态不正确,或者是按键开门,就不录入数据
if (cardRecord.bStatus != 1 || "00000000".equals(cardNo)) {
continue;
}
// 刷卡时间 转换为北京时间 +8小时
Date stuTime = DateUtil.convertStringToDate(cardRecord.stuTime.toStringTimeEx(), "yyyy-MM-dd HH:mm:ss");
Calendar stuCalendar = DateUtil.getCalendar(stuTime);
stuCalendar.add(Calendar.HOUR, 8);
}
}