提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
公司要求对接海康威视的道闸系统进行数据展示,但是官方sdk中的演示java文件是有交互界面的,不符合controller层代码逻辑,因此需要改写。
一、ISAPI是什么?
ISAPI全称为Intelligent Security API(智能安全API),是基于HTTP(Hypertext Transfer Protocol)的应用层协议,并采用REST架构(Representational State Transfer, 表述性状态转移),实现安防设备(如摄像机、数字录像机、网络录像机等)与平台或客户端软件之间的通信。
二、修改步骤
1.改写的controller代码
代码如下(示例):
package com.jsdhqy.science.controller;
import com.alibaba.nacos.common.http.param.MediaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsdhqy.science.HCNetSDK;
import com.jsdhqy.science.osSelect;
import com.sun.jna.Native;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpHeaders;
import javax.swing.*;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
/**
* 海康威视ISAPI
*
* @author ftao
* @since 2023-08-01
*/
@RestController
@AllArgsConstructor
@RequestMapping("hikvision")
public class HikvisionController {
static HCNetSDK hCNetSDK = null;
public static final int ISAPI_DATA_LEN = 1024*1024;
public static final int ISAPI_STATUS_LEN = 4*4096;
public static final int BYTE_ARRAY_LEN = 1024;
/**
* 加载库,SDK初始化
*/
public void HikvisionInit() {
if (hCNetSDK == null) {
if (!createSDKInstance()) {
System.out.println("Load SDK fail");
return;
}
}
// Linux系统建议调用以下接口加载组件库
if (osSelect.isLinux()) {
HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
// 这里是库的绝对路径,请根据实际情况修改,注意该路径必须有访问权限
String strPath1 = System.getProperty("user.dir") + "/lib/libcrypto.so.1.1";
String strPath2 = System.getProperty("user.dir") + "/lib/libssl.so.1.1";
System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
ptrByteArray1.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());
System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
ptrByteArray2.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());
String strPathCom = System.getProperty("user.dir") + "/lib/";
//System.out.println("lib所在目录在: " + System.getProperty("user.dir") + "/lib/");
HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
struComPath.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
}
boolean initSuc = hCNetSDK.NET_DVR_Init();
if (!initSuc) {
System.out.println("初始化失败");
}
// 加载日志
boolean setLogSuc = hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
if (!setLogSuc) {
System.out.println("加载日志失败");
}
}
/**
* 初始化SDK实例
*
* @return 初始化是否成功
*/
public boolean createSDKInstance() {
if (hCNetSDK == null) {
synchronized (HCNetSDK.class) {
String strDllPath = "";
try {
if (osSelect.isWindows()) {
// Win系统加载SDK库路径
strDllPath = System.getProperty("user.dir") + "\\lib\\HCNetSDK.dll";
System.out.println("SDK所在目录: "+System.getProperty("user.dir") + "\\lib\\HCNetSDK.dll");
} else if (osSelect.isLinux()) {
// Linux系统加载SDK库路径
strDllPath = System.getProperty("user.dir") + "/lib/libhcnetsdk.so";
}
hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
} catch (Exception ex) {
System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
/**
* 注册登录用户
* @return
*/
@GetMapping("/ISAPI/login")
public String login() {
int lUserID = -1; // 用户句柄,将lUserID声明为实例变量并初始化为-1
//注册之前先注销已注册的用户,预览情况下不可注销
try {
hCNetSDK.NET_DVR_Logout(lUserID);
}
catch (Exception e){
System.out.println("未注册");
}
HikvisionInit();
//注册
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
String sDeviceIP = "10.0.11.100";//登录设备IP地址
String sUsername = "admin";//设备用户名
String sPassword = "hik12345+";//设备密码
int portNumber = 8000;
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
System.arraycopy(sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, sDeviceIP.length());
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
System.arraycopy(sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, sUsername.length());
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
System.arraycopy(sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, sPassword.length());
m_strLoginInfo.wPort = (short) portNumber;
m_strLoginInfo.byLoginMode = 0;
m_strLoginInfo.byHttps = 0;
m_strLoginInfo.bUseAsynLogin = false;
m_strLoginInfo.write();
try {
lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
System.out.println(lUserID);
if(lUserID <= -1){
System.out.println("注册失败,错误号:" + hCNetSDK.NET_DVR_GetLastError());
}
else {
System.out.println("注册成功");
}
}
catch(Exception e){
System.out.println("lUserID: " + lUserID);
//System.out.println("注册失败,错误号:" + hCNetSDK.NET_DVR_GetLastError());
return "注册出错";
}
//return "";
//原方法
if (lUserID == -1)
{
return "请先注册";
}
HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
struXMLInput.read();
struXMLInput.dwSize = struXMLInput.size();
String strURL = "POST /ISAPI/Parking/server/passVehicleInfo/recordSearch";
int iURLlen = strURL.length();
HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(iURLlen+1);
System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length());
ptrUrl.write();
struXMLInput.lpRequestUrl = ptrUrl.getPointer();
struXMLInput.dwRequestUrlLen = iURLlen;
String strInbuffer = "";
//拉取所有数据保存到数据库中,从6月1到今天,后续查询使用distinct筛除重复
LocalDate startDate = LocalDate.of(java.time.LocalDate.now().getYear(), 6, 1);
LocalDate endDate = java.time.LocalDate.now();
long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
//查询最大间隔为7天
for (int j = 0; j <= daysBetween; j += 6) {
LocalDate currentStartDate = startDate.plusDays(j);
LocalDateTime currentEndDate = currentStartDate.plusDays(5).atTime(23, 59, 59);
//每页最大数量为100,平均每天数量为2000+,设置最大为3000
for (int i = 0; i <= 3000; i += 100) {
String searchResultPosition = Integer.toString(i);
String jsonString = "{\"PassVehicleInfoSearchDescription\":{\"searchID\":\"\",\"searchResultPosition\":" + searchResultPosition + ",\"maxResults\":100,\"parkingID\":\"all\",\"gateID\":\"all\",\"laneID\":\"all\",\"licensePlate\":\"\",\"cardNo\":\"\",\"direction\":\"all\",\"operationType\":\"all\",\"parkingType\":\"all\",\"executeControlVehicle\":{\"enabled\":2},\"orderType\":\"DESC\",\"remoteHost\":3,\"sendFlag\":\"all\",\"startTime\":\"" + currentStartDate + "\",\"endTime\":\"" + currentEndDate + "\"}}";
strInbuffer = jsonString;
System.out.println(strInbuffer);
//String strInbuffer = "{\"PassVehicleInfoSearchDescription\":{\"searchID\":\"\",\"searchResultPosition\":0,\"maxResults\":100,\"parkingID\":\"all\",\"gateID\":\"all\",\"laneID\":\"all\",\"licensePlate\":\"\",\"cardNo\":\"\",\"direction\":\"all\",\"operationType\":\"all\",\"parkingType\":\"all\",\"executeControlVehicle\":{\"enabled\":2},\"orderType\":\"DESC\",\"remoteHost\":3,\"sendFlag\":\"all\",\"startTime\":\""+String.format("%d-01-01T00:00:00Z", java.time.LocalDate.now().getYear())+"\",\"endTime\":\""+String.format("%d-12-31T23:59:59Z", java.time.LocalDate.now().getYear())+"\"}}";
int iInBufLen = strInbuffer.length();
if (iInBufLen == 0) {
struXMLInput.lpInBuffer = null;
struXMLInput.dwInBufferSize = 0;
struXMLInput.write();
} else {
HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(iInBufLen + 1);
ptrInBuffer.read();
ptrInBuffer.byValue = strInbuffer.getBytes();
ptrInBuffer.write();
struXMLInput.lpInBuffer = ptrInBuffer.getPointer();
struXMLInput.dwInBufferSize = iInBufLen;
struXMLInput.write();
}
HCNetSDK.BYTE_ARRAY ptrStatusByte = new HCNetSDK.BYTE_ARRAY(ISAPI_STATUS_LEN);
ptrStatusByte.read();
HCNetSDK.BYTE_ARRAY ptrOutByte = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN);
ptrOutByte.read();
HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT struXMLOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
struXMLOutput.read();
struXMLOutput.dwSize = struXMLOutput.size();
struXMLOutput.lpOutBuffer = ptrOutByte.getPointer();
struXMLOutput.dwOutBufferSize = ptrOutByte.size();
struXMLOutput.lpStatusBuffer = ptrStatusByte.getPointer();
struXMLOutput.dwStatusSize = ptrStatusByte.size();
struXMLOutput.write();
if (!hCNetSDK.NET_DVR_STDXMLConfig(lUserID, struXMLInput, struXMLOutput)) {
int iErr = hCNetSDK.NET_DVR_GetLastError();
return "NET_DVR_STDXMLConfig失败,错误号:" + iErr;
} else {
struXMLOutput.read();
ptrOutByte.read();
ptrStatusByte.read();
String strOutXML = new String(ptrOutByte.byValue).trim();
//System.out.println(strOutXML);
//报错到数据库
// 解析JSON
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode jsonNode = objectMapper.readTree(strOutXML);
JsonNode matchList = jsonNode.get("MatchList");
if (matchList.isArray()) {
for (JsonNode match : matchList) {
// 从JSON中提取字段值
String gate_name = match.get("gateName").asText();
//System.out.println(gate_name);
String lane_name = match.get("laneName").asText();
//System.out.println(lane_name);
String operation_type = match.get("operationType").asText();
String license_plate = match.get("licensePlate").asText();
System.out.println(license_plate);
String pass_time = match.get("passTime").asText();
System.out.println(pass_time);
String direction = match.get("direction").asText();
String release_reason = match.get("releaseReason").asText();
// 这里进行其他的操作
}
}
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println("strOutXML " + strOutXML);
//String strStatus = new String(ptrStatusByte.byValue).trim();
//System.out.println("strStatus " + strStatus);
}
}
}
//退出程序时调用,每一台设备分别注销
if (hCNetSDK.NET_DVR_Logout(lUserID)) {
System.out.println("注销成功");
}
//SDK反初始化,释放资源,只需要退出时调用一次
hCNetSDK.NET_DVR_Cleanup();
return "请求结束";
}
/**
* 注销登录用户
* @return
*/
@GetMapping("/ISAPI/logout")
public String loginout() {
HikvisionInit();
//录设备的用户数达到最大时,手动清理的方法
int lUserID;
for (lUserID=125;lUserID>=1;lUserID--) {
//退出程序时调用,每一台设备分别注销
if (hCNetSDK.NET_DVR_Logout(lUserID)) {
System.out.println("注销成功" + lUserID);
}
//SDK反初始化,释放资源,只需要退出时调用一次
hCNetSDK.NET_DVR_Cleanup();
System.out.println("清理结束");
}
return "定时任务结束";
}
}
2.HCNetSDK.java
在改动controller层后,HCNetSDK的参数数据上也要改写,不过很简单,在涉及的方法中添加getFieldOrder返回方法即可,可以参考他已经写的getFieldOrder来改写。
3.osSelect.java
原封不动复制过来即可。
最后将Controller文件、HCNetSDK、osSelect放在controller文件夹中即可