当前位置:   article > 正文

Java二次开发海康SDK-对接门禁机一文全解_java如何与硬件对接实现门禁管理

java如何与硬件对接实现门禁管理

写在最前

SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64

参考文档:海康SDK使用手册_V6.1

对接测试设备型号:DS-K1T671M

设备序列号:E50247795

业务目标

使用门禁设备实现对人脸的抓拍,将抓拍的人脸与其对应的数据进行上传。

业务流程图:

业务流程节点解释:

1.初始化SDK(NET_DVR_Init):进行海康提供开发库的载入,使用海康官方提供的文件库,进入之后,修改载入路径就可以了。

2.设置报警回调函数(NET_DVR_SetDVRMessageCallBack_V31):初始完SDK之后,进行报警回调函数的设置,当设备进行人脸抓拍之后,上传报警信息到SDK,触发回调函数进行内部业务逻辑处理。对于(门禁设备)人脸侦测,回调函数中的报警类型(lCommand)为COMM_ALARM_ACS,,报警信息(pAlarmInfo)对应结构体:NET_DVR_ACS_ALARM_INFO。

3.用户注册(NET_DVR_Login_V40):填写设备对应的设备参数,进行设备的注册,注册成功会返回一个lUserID,使用这个lUserID进行下面一系列的操作。

4.获取设备能力集(NET_DVR_GetDeviceAbility):能力集类型DEVICE_ABILITY_INFO,获取智能通道分析能力集可以判断设备是否支持相关功能。(可选功能)

5.设置人脸抓拍参数(NET_DVR_SetDVRConfig) (可选功能)

6.获取人脸抓拍参数(NET_DVR_GetDVRConfig) (可选功能)

7.报警布防(NET_DVR_SetupAlarmChan_v41):布防即建立设备跟客户端之间报警上传的连接通道,这样设备发生报警之后通过该连接上传报警信息,SDK在报警回调函数中接收和处理报警信息数据即可。如果设备同时支持人脸侦测和人脸抓拍方式,调用该接口时,NET_DVR_SETUPALARM_PARAM布防参数中byFaceAlarmDetection赋值为0即选择设备上传的报警信息类型为人脸抓拍类型。

注意:在报警布防中需要设置连接的参数,设置不对或没有设置会提示连接设备失败。

8.报警回调函数里面接收和处理数据:报警类型:COMM_ALARM_ACS,报警信息结构体:NET_DVR_ACS_ALARM_INFO。对设备上传来的数据信息进行接收

9.报警撤防(NET_DVR_CloseAlarmChan_v30)

10.注销用户(NET_DVR_logout)

11.释放SDK资源(NET_DVR_Cleanup):关闭连接通道,释放资源。

代码示例

1.首先根据你需要开发的系统去海康官网下载对应的程序包。

比如我的win64

2. 创建好springboot项目,将这个程序包里面的库文件引进去。

3. 将程序包里面它提供的 HCNetSDK.java 复制到你的项目里面,并修改你刚才放的库文件路径,注意以.dll结尾

4. 接下来就是写 demo 测试连接

  1. package com.example.testsdk;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.io.IOException;
  5. /**
  6. * @author LH
  7. */
  8. public class startHCNetAlarm {
  9. private static final Logger LOGGER = LoggerFactory.getLogger(startHCNetAlarm.class);
  10. // 载入sdk库文件
  11. static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
  12. public static void main(String[] args) throws IOException {
  13. HCNetAlarm hcNetAlarm = new HCNetAlarm();
  14. // 资源初始化
  15. int row = hcNetAlarm.initDevice();
  16. if (row == 1) {
  17. LOGGER.info("初始化失败");
  18. }
  19. // 设置连接超时时间与重连功能
  20. hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
  21. hCNetSDK.NET_DVR_SetReconnect(10000, true);
  22. // 设备注册,注册成功返回一个唯一标识符 lUserID,根据这个进行设备的其它操作
  23. int luserID = hcNetAlarm.deviceRegister(-1, "填你设备的ip地址", "设备用户名", "设备密码", "设备端口,一般默认8000");
  24. System.out.println(luserID);
  25. // 设置报警回调函数,建立报警上传通道(启用布防)
  26. int lAlarmHandle = hcNetAlarm.setupAlarmChan(luserID, -1);
  27. // 检查设备状态(是否在线),打印设备信息
  28. hcNetAlarm.onlineState(luserID);
  29. // 设备抓拍功能,
  30. // hcNetAlarm.getDVRPic(luserID);
  31. try {
  32. // 等待设备上传报警信息
  33. LOGGER.info("等待设备上传报警信息====================");
  34. Thread.sleep(100 * 60 * 60);
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. // 撤销布防上传通道
  39. hcNetAlarm.closeAlarmChan(lAlarmHandle);
  40. // 注销 释放sdk资源
  41. hcNetAlarm.logout(luserID);
  42. System.out.println("====== 设备注销 ======");
  43. }
  44. }
  1. package com.example.testsdk;
  2. import com.sun.jna.NativeLong;
  3. import com.sun.jna.Pointer;
  4. import com.sun.jna.ptr.IntByReference;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import java.io.File;
  8. import java.io.FileNotFoundException;
  9. import java.io.FileOutputStream;
  10. import java.io.IOException;
  11. import java.nio.ByteBuffer;
  12. import java.text.DateFormat;
  13. import java.text.SimpleDateFormat;
  14. import java.util.Arrays;
  15. import java.util.Date;
  16. /**
  17. * @author LH
  18. */
  19. public class HCNetAlarm {
  20. private static final Logger LOGGER = LoggerFactory.getLogger(HCNetAlarm.class);
  21. // 载入sdk库文件
  22. static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
  23. // 设备登录信息
  24. HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
  25. // 设备信息
  26. HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
  27. // 已登录设备的IP
  28. String m_sDeviceIP;
  29. // 设备用户名
  30. String m_sUsername;
  31. // 设备密码
  32. String m_sPassword;
  33. // 报警回调函数实现
  34. public static HCNetSDK.FMSGCallBack_V31 fMSFCallBack_V31;
  35. /**
  36. * sdk初始化
  37. *
  38. * @return
  39. */
  40. public int initDevice() {
  41. if (!hCNetSDK.NET_DVR_Init()) {
  42. // sdk初始化失败
  43. return 1;
  44. }
  45. return 0;
  46. }
  47. /**
  48. * 注销
  49. *
  50. * @param lUserID 设备注册成功唯一标识符
  51. */
  52. public void logout(int lUserID) {
  53. // 注销
  54. hCNetSDK.NET_DVR_Logout(lUserID);
  55. // 释放sdk资源
  56. hCNetSDK.NET_DVR_Cleanup();
  57. }
  58. /**
  59. * 设备注册
  60. *
  61. * @param ip 设备ip
  62. * @param name 设备名
  63. * @param password 设备密码
  64. */
  65. public int deviceRegister(int lUserID, String ip, String name, String password, String port) {
  66. // 设备注册之前先进行判断,注销已注册的设备
  67. if (lUserID > -1) {
  68. // 先注销
  69. hCNetSDK.NET_DVR_Logout(lUserID);
  70. lUserID = -1;
  71. }
  72. // ip地址
  73. m_sDeviceIP = ip;
  74. m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
  75. System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
  76. // 设备用户名
  77. m_sUsername = name;
  78. m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
  79. System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
  80. // 设备密码
  81. m_sPassword = password;
  82. m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
  83. System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
  84. m_strLoginInfo.wPort = (short) Integer.parseInt(port);
  85. // 是否异步登录:0 - 否,1 - 是
  86. m_strLoginInfo.bUseAsynLogin = false;
  87. m_strLoginInfo.write();
  88. // 设备注册调用 NET_DVR_Login_V40,注册成功得到唯一标识符 lUserID
  89. // 设备注册失败,调用 NET_DVR_GetLastError,根据错误号判断错误类型
  90. lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
  91. if (lUserID == -1) {
  92. LOGGER.info("设备注册失败,错误号:", hCNetSDK.NET_DVR_GetLastError());
  93. return -1;
  94. } else {
  95. LOGGER.info("设备注册成功");
  96. return lUserID;
  97. }
  98. }
  99. /**
  100. * 设置报警信息回调函数,根据上传的数据进行回调触发
  101. */
  102. public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
  103. // lCommand 上传消息类型,这个是设备上传的数据类型,比如现在测试的门禁设备,回传回来的是 COMM_ALARM_ACS = 0x5002; 门禁主机报警信息
  104. // pAlarmer 报警设备信息
  105. // pAlarmInfo 报警信息 根据 lCommand 来选择接收的报警信息数据结构
  106. // dwBufLen 报警信息缓存大小
  107. // pUser 用户数据
  108. @Override
  109. public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
  110. alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
  111. return true;
  112. }
  113. }
  114. /**
  115. * 建立布防上传通道,用于传输数据
  116. *
  117. * @param lUserID 唯一标识符
  118. * @param lAlarmHandle 报警处理器
  119. */
  120. public int setupAlarmChan(int lUserID, int lAlarmHandle) {
  121. // 根据设备注册生成的lUserID建立布防的上传通道,即数据的上传通道
  122. if (lUserID == -1) {
  123. LOGGER.info("请先注册");
  124. return lUserID;
  125. }
  126. if (lAlarmHandle < 0) {
  127. // 设备尚未布防,需要先进行布防
  128. if (fMSFCallBack_V31 == null) {
  129. fMSFCallBack_V31 = new FMSGCallBack_V31();
  130. Pointer pUser = null;
  131. if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
  132. LOGGER.info("设置回调函数失败!", hCNetSDK.NET_DVR_GetLastError());
  133. }
  134. }
  135. // 这里需要对设备进行相应的参数设置,不设置或设置错误都会导致设备注册失败
  136. HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
  137. m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
  138. // 智能交通布防优先级:0 - 一等级(高),1 - 二等级(中),2 - 三等级(低)
  139. m_strAlarmInfo.byLevel = 1;
  140. // 智能交通报警信息上传类型:0 - 老报警信息(NET_DVR_PLATE_RESULT), 1 - 新报警信息(NET_ITS_PLATE_RESULT)
  141. m_strAlarmInfo.byAlarmInfoType = 1;
  142. // 布防类型(仅针对门禁主机、人证设备):0 - 客户端布防(会断网续传),1 - 实时布防(只上传实时数据)
  143. m_strAlarmInfo.byDeployType = 1;
  144. // 抓拍,这个类型要设置为 0 ,最重要的一点设置
  145. m_strAlarmInfo.byFaceAlarmDetection = 0;
  146. m_strAlarmInfo.write();
  147. // 布防成功,返回布防成功的数据传输通道号
  148. lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, m_strAlarmInfo);
  149. if (lAlarmHandle == -1) {
  150. LOGGER.info("设备布防失败,错误码=========={}", hCNetSDK.NET_DVR_GetLastError());
  151. // 注销 释放sdk资源
  152. logout(lUserID);
  153. return lAlarmHandle;
  154. } else {
  155. LOGGER.info("设备布防成功");
  156. return lAlarmHandle;
  157. }
  158. }
  159. return lAlarmHandle;
  160. }
  161. /**
  162. * 报警撤防
  163. *
  164. * @param lAlarmHandle 报警处理器
  165. */
  166. public int closeAlarmChan(int lAlarmHandle) {
  167. if (lAlarmHandle > -1) {
  168. if (hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle)) {
  169. LOGGER.info("撤防成功");
  170. lAlarmHandle = -1;
  171. return lAlarmHandle;
  172. }
  173. return lAlarmHandle;
  174. }
  175. return lAlarmHandle;
  176. }
  177. /**
  178. * 接收设备上传的报警信息,进行上传数据的业务逻辑处理
  179. *
  180. * @param lCommand 上传消息类型
  181. * @param pAlarmer 报警设备信息
  182. * @param pAlarmInfo 报警信息
  183. * @param dwBufLen 报警信息缓存大小
  184. * @param pUser 用户数据
  185. */
  186. public void alarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
  187. System.out.println("报警监听中================================");
  188. System.out.println(pAlarmInfo);
  189. String sAlarmType = new String();
  190. String[] newRow = new String[3];
  191. //报警时间
  192. Date today = new Date();
  193. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
  194. String[] sIP = new String[2];
  195. sAlarmType = new String("lCommand=0x") + Integer.toHexString(lCommand);
  196. // lCommand是传的报警类型
  197. switch (lCommand) {
  198. // 摄像头实时人脸抓拍上传
  199. case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT:
  200. // 分配存储空间
  201. HCNetSDK.NET_VCA_FACESNAP_RESULT strFaceSnapInfo = new HCNetSDK.NET_VCA_FACESNAP_RESULT();
  202. strFaceSnapInfo.write();
  203. Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();
  204. // 写入传入数据
  205. pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
  206. strFaceSnapInfo.read();
  207. sAlarmType = sAlarmType + ":人脸抓拍上传[人脸评分:" + strFaceSnapInfo.dwFaceScore + ",年龄:" + strFaceSnapInfo.struFeature.byAge + ",性别:" + strFaceSnapInfo.struFeature.bySex + "]";
  208. newRow[0] = dateFormat.format(today);
  209. // 报警类型
  210. newRow[1] = sAlarmType;
  211. // 报警设备IP地址
  212. sIP = new String(strFaceSnapInfo.struDevInfo.struDevIP.sIpV4).split("\0", 2);
  213. newRow[2] = sIP[0];
  214. LOGGER.info("人脸抓拍========{}", Arrays.toString(newRow));
  215. // 设置日期格式
  216. SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
  217. // new Date()为获取当前系统时间
  218. String time = df.format(new Date());
  219. // 人脸图片写文件
  220. File file = new File(System.getProperty("user.dir") + "\\pic1\\");
  221. if (!file.exists()) {
  222. file.mkdir();
  223. }
  224. try {
  225. FileOutputStream big = new FileOutputStream(System.getProperty("user.dir") + "\\pic1\\" + time + "background.jpg");
  226. if (strFaceSnapInfo.dwFacePicLen > 0) {
  227. if (strFaceSnapInfo.dwFacePicLen > 0) {
  228. try {
  229. big.write(strFaceSnapInfo.pBuffer2.getByteArray(0, strFaceSnapInfo.dwBackgroundPicLen), 0, strFaceSnapInfo.dwBackgroundPicLen);
  230. big.close();
  231. } catch (IOException e) {
  232. e.printStackTrace();
  233. }
  234. }
  235. }
  236. } catch (FileNotFoundException e) {
  237. e.printStackTrace();
  238. }
  239. break;
  240. // 门禁主机类型实时人脸抓拍上传,走这里
  241. case HCNetSDK.COMM_ALARM_ACS:
  242. // 分配存储空间
  243. System.out.println("============ 这是门禁主机的报警信息 ============");
  244. HCNetSDK.NET_DVR_ACS_ALARM_INFO strFaceSnapInfo1 = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
  245. strFaceSnapInfo1.write();
  246. Pointer pFaceSnapInfo1 = strFaceSnapInfo1.getPointer();
  247. // 写入传入数据
  248. pFaceSnapInfo1.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo1.size()), 0, strFaceSnapInfo1.size());
  249. strFaceSnapInfo1.read();
  250. // 设置日期格式
  251. SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMddHHmmss");
  252. // new Date()为获取当前系统时间
  253. String time1 = df1.format(new Date());
  254. // 人脸图片写文件
  255. File file1 = new File(System.getProperty("user.dir") + "\\pic3\\");
  256. if (!file1.exists()) {
  257. file1.mkdir();
  258. }
  259. try {
  260. FileOutputStream big = new FileOutputStream(System.getProperty("user.dir") + "\\pic3\\" + time1 + ".jpg");
  261. if (strFaceSnapInfo1.dwPicDataLen > 0) {
  262. System.out.println("========== 图片有数据 ========");
  263. if (strFaceSnapInfo1.dwPicDataLen > 0) {
  264. try {
  265. System.out.println("============ 图片上传成功 =============");
  266. big.write(strFaceSnapInfo1.pPicData.getByteArray(0, strFaceSnapInfo1.dwPicDataLen), 0, strFaceSnapInfo1.dwPicDataLen);
  267. big.close();
  268. System.out.println("设备唯一编码=================" + strFaceSnapInfo1.struAcsEventInfo.byDeviceNo);
  269. System.out.println("数据采集时间=================" + strFaceSnapInfo1.struTime.dwYear + strFaceSnapInfo1.struTime.dwMonth + strFaceSnapInfo1.struTime.dwDay + strFaceSnapInfo1.struTime.dwHour + strFaceSnapInfo1.struTime.dwMinute + strFaceSnapInfo1.struTime.dwSecond);
  270. System.out.println("人员工号=================" + strFaceSnapInfo1.struAcsEventInfo.dwEmployeeNo);
  271. System.out.println("人员姓名=================" + strFaceSnapInfo1.sNetUser);
  272. System.out.println("通进类型(0:入场,1:离场)=================" + strFaceSnapInfo1.struAcsEventInfo.dwDoorNo);
  273. System.out.println("图片唯一标识(工号加时间)=================" + strFaceSnapInfo1.struAcsEventInfo.dwEmployeeNo + time1 + ".jpg");
  274. System.out.println("人员类型(0:白名单,1:访客,2:黑名单)=================" + strFaceSnapInfo1.struAcsEventInfo.byCardType);
  275. } catch (IOException e) {
  276. e.printStackTrace();
  277. }
  278. }
  279. }
  280. } catch (FileNotFoundException e) {
  281. e.printStackTrace();
  282. }
  283. break;
  284. default:
  285. newRow[0] = dateFormat.format(today);
  286. // 报警类型
  287. newRow[1] = sAlarmType;
  288. // 报警设备IP地址
  289. sIP = new String(pAlarmer.sDeviceIP).split("\0", 2);
  290. newRow[2] = sIP[0];
  291. LOGGER.info("其他报警信息=========={}", Arrays.toString(newRow));
  292. break;
  293. }
  294. }
  295. // 抓拍图片
  296. public static void getDVRPic(int userId) throws IOException {
  297. // 设置通道号,其中 1 正常,-1不正常
  298. NativeLong chanLong = new NativeLong(1);
  299. // 返回Boolean值,判断是否获取设备能力
  300. HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
  301. if (!hCNetSDK.NET_DVR_GetDVRWorkState_V30(userId, devwork)) {
  302. System.out.println("返回设备状态失败");
  303. }
  304. // JPEG图像信息结构体
  305. HCNetSDK.NET_DVR_JPEGPARA jpeg = new HCNetSDK.NET_DVR_JPEGPARA();
  306. jpeg.wPicSize = 2; // 设置图片的分辨率
  307. jpeg.wPicQuality = 2; // 设置图片质量
  308. IntByReference a = new IntByReference();
  309. SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
  310. Date date = new Date();
  311. int random = (int) (Math.random() * 1000);
  312. String fileNameString = sdf.format(date) + random + ".jpg";
  313. // 设置字节缓存
  314. ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
  315. // 抓图到文件
  316. boolean is = hCNetSDK.NET_DVR_CaptureJPEGPicture(userId, chanLong.intValue(), jpeg, fileNameString);
  317. if (is) {
  318. System.out.println("图片抓取成功,返回长度:" + a.getValue());
  319. } else {
  320. System.out.println("图片抓取失败:" + hCNetSDK.NET_DVR_GetLastError());
  321. }
  322. }
  323. /**
  324. * 设备状态,是否在线,打印设备信息
  325. */
  326. public Boolean onlineState(int lUserID) {
  327. HCNetAlarm hcNetAlarm = new HCNetAlarm();
  328. int row = hcNetAlarm.initDevice();
  329. if (row == 1) {
  330. LOGGER.info("初始化失败");
  331. }
  332. // 检查设备在线状态
  333. LOGGER.info("设备信息========={}", hcNetAlarm.m_strDeviceInfo.struDeviceV30);
  334. boolean isOnLine = hCNetSDK.NET_DVR_RemoteControl(lUserID, 20005, null, 0);
  335. LOGGER.info("checkDeviceOnLine---isOnLine============{}", isOnLine);
  336. return isOnLine;
  337. }
  338. }

写在结尾

遇到的问题:无法上传图片。(官方文档有点坑)

可能原因:刚开始以为是设备不支持抓拍功能。

解决方式:一遍一遍地阅读官方文档,换了一个又一个接口,最后发现,官方文档上提示的抓拍功能流程图是基于海康摄像头的,但是我使用的设备是海康的门禁设备,两者虽然大体相似,但是还是有不同之处,对于不同的设备需要进行不同的判断。

如这次使用的设备是门禁设备,首先根据触发回调返回的lCommand 进行设备区分,本次测试返回的 lCommand = 0x5002, 即门禁主机报警信息,然后去官方文档上查看对应的sdk接收信息体,为NET_DVR_ACS_ALARM_INFO。这样才能正确接收设备传过来的数据,也能得到上传的图片及其对应的人员信息。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/709857
推荐阅读
相关标签
  

闽ICP备14008679号