package com.ard.utils.sdk.hiksdk.service;
|
|
import com.ard.alarm.camera.domain.ArdCameras;
|
import com.ard.alarm.camera.domain.CameraCmd;
|
import com.ard.alarm.external.domain.ArdEquipExternal;
|
import com.ard.utils.minio.MinioUtil;
|
import com.ard.utils.sdk.hiksdk.domain.ChannelInfo;
|
import com.ard.utils.util.ByteUtils;
|
import com.ard.utils.sdk.hiksdk.common.GlobalVariable;
|
import com.ard.utils.sdk.hiksdk.domain.DeviceInfo;
|
import com.ard.utils.sdk.hiksdk.util.hikSdkUtil.HCNetSDK;
|
import com.sun.jna.NativeLong;
|
import com.sun.jna.Platform;
|
import com.sun.jna.Pointer;
|
import com.sun.jna.ptr.IntByReference;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.io.*;
|
import java.nio.ByteBuffer;
|
import java.util.*;
|
|
/**
|
* @ClassName: hikClientServiceImpl
|
* @Description: 海康操作客户端实现类
|
* @Author: Administrator
|
* @Date: 2023年01月17日 11:25
|
* @Version: 1.2
|
**/
|
@Slf4j(topic = "hikSdk")
|
public class HikClientUtil {
|
public static HCNetSDK hCNetSDK = HCNetSDK.hCNetSDK;
|
// 报警回调函数实现
|
public static HCNetSDK.FMSGCallBack_V31 fMSFCallBack_V31;
|
|
/**
|
* @描述 注册登录 集成于NET_DVR_Login_V30,支持同步和异步登录
|
* @创建人 刘苏义
|
* @创建时间 2023/1/17 16:12
|
*/
|
public static int login(DeviceInfo deviceInfo) {
|
// 初始化
|
if (!hCNetSDK.NET_DVR_Init()) {
|
log.error("SDK初始化失败");
|
}
|
//设置JSON透传报警数据和图片分离
|
HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
|
struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1; //设置JSON透传报警数据和图片分离
|
struNET_DVR_LOCAL_GENERAL_CFG.write();
|
Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();
|
hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);
|
|
//打印海康sdk日志
|
if (Platform.isWindows()) {
|
String WIN_PATH = System.getProperty("user.dir") + File.separator + "ardLog" + File.separator + "logs" + File.separator;
|
hCNetSDK.NET_DVR_SetLogToFile(3, WIN_PATH, true);
|
} else {
|
hCNetSDK.NET_DVR_SetLogToFile(3, "/home/ardLog/hiklog", true);
|
}
|
String m_sDeviceIP = deviceInfo.getIp();
|
String m_sUsername = deviceInfo.getUsername();
|
String m_sPassword = deviceInfo.getPassword();
|
short m_sPort = deviceInfo.getPort().shortValue();
|
//设置连接时间与重连时间
|
hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
|
hCNetSDK.NET_DVR_SetReconnect(100000, true);
|
//设备信息, 输出参数
|
HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
|
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
|
|
// 注册设备-登录参数,包括设备地址、登录用户、密码等
|
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
|
System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
|
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
|
System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
|
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
|
System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
|
m_strLoginInfo.wPort = m_sPort;
|
m_strLoginInfo.byVerifyMode = 0;
|
m_strLoginInfo.byLoginMode = 0;
|
//是否异步登录:0- 否,1- 是 windowsSDK里是true和false
|
m_strLoginInfo.bUseAsynLogin = true;
|
//异步登录回调
|
m_strLoginInfo.cbLoginResult = new LoginResultCallBack(deviceInfo);
|
m_strLoginInfo.write();
|
int loginId = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
|
if (loginId < 0) {
|
int errorCode = hCNetSDK.NET_DVR_GetLastError();
|
log.error("登录异常:" + errorCode);
|
}
|
return loginId;
|
}
|
|
/**
|
* @描述 用户注销
|
* @创建人 刘苏义
|
* @创建时间 2023/1/17 16:12
|
*/
|
public static void logout(DeviceInfo deviceInfo) {
|
String deviceIpPort = deviceInfo.getIp() + ":" + deviceInfo.getPort();
|
//撤防
|
if (GlobalVariable.alarmMap.containsKey(deviceInfo.getDeviceId())) {
|
Integer lAlarmHandle = GlobalVariable.alarmMap.get(deviceInfo.getDeviceId());
|
boolean b = hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle);
|
if (b) {
|
log.debug("设备【" + deviceIpPort + "】撤防成功");
|
}
|
}
|
//登出
|
if (GlobalVariable.loginMap.containsKey(deviceInfo.getDeviceId())) {
|
Integer lUserID = GlobalVariable.loginMap.get(deviceInfo.getDeviceId());
|
boolean b = hCNetSDK.NET_DVR_Logout(lUserID);
|
if (b) {
|
log.debug("设备【" + deviceIpPort + "】注销成功");
|
}
|
}
|
}
|
|
/**
|
* @描述 登录所有相机
|
* @创建人 刘苏义
|
* @创建时间 2023/2/3 10:10
|
*/
|
public static void loginAllCamera(List<ArdCameras> ardCameras) {
|
try {
|
for (ArdCameras camera : ardCameras) {
|
Thread.sleep(100);
|
DeviceInfo info = new DeviceInfo();
|
info.setDeviceId(camera.getId());
|
info.setIp(camera.getIp());
|
info.setPort(camera.getPort());
|
info.setUsername(camera.getUsername());
|
info.setPassword(camera.getPassword());
|
info.setDeviceType(camera.getGdType());
|
login(info);
|
String key = camera.getIp() + ":" + camera.getPort();
|
GlobalVariable.cameraMap.put(key, camera);
|
}
|
} catch (Exception ex) {
|
log.error("登录相机异常:" + ex.getMessage());
|
}
|
}
|
|
/**
|
* @描述 登出所有相机
|
* @创建人 刘苏义
|
* @创建时间 2023/2/3 10:10
|
*/
|
public static void logoutAllCamera(List<ArdCameras> ardCameras) {
|
try {
|
for (ArdCameras camera : ardCameras) {
|
Thread.sleep(100);
|
DeviceInfo info = new DeviceInfo();
|
info.setDeviceId(camera.getId());
|
info.setIp(camera.getIp());
|
info.setPort(camera.getPort());
|
info.setUsername(camera.getUsername());
|
info.setPassword(camera.getPassword());
|
logout(info);
|
String key = camera.getIp() + ":" + camera.getPort();
|
GlobalVariable.cameraMap.remove(key);
|
}
|
} catch (Exception ex) {
|
log.error("注销相机异常:" + ex.getMessage());
|
}
|
}
|
|
/**
|
* @描述 登录所有外联设备
|
* @创建人 刘苏义
|
* @创建时间 2023/2/3 10:10
|
*/
|
public static void loginAllArdEquipExternals(List<ArdEquipExternal> ardEquipExternals) {
|
try {
|
for (ArdEquipExternal ardEquipExternal : ardEquipExternals) {
|
Thread.sleep(100);
|
DeviceInfo info = new DeviceInfo();
|
info.setDeviceId(ardEquipExternal.getId());
|
info.setIp(ardEquipExternal.getIp());
|
info.setPort(ardEquipExternal.getPort());
|
info.setUsername(ardEquipExternal.getUsername());
|
info.setPassword(ardEquipExternal.getPassword());
|
login(info);
|
}
|
} catch (Exception ex) {
|
log.error("登录所有外联设备异常:" + ex.getMessage());
|
}
|
}
|
|
/**
|
* @描述 登出所有外联设备
|
* @创建人 刘苏义
|
* @创建时间 2023/2/3 10:10
|
*/
|
public static void logoutAllArdEquipExternals(List<ArdEquipExternal> ardEquipExternals) {
|
try {
|
for (ArdEquipExternal ardEquipExternal : ardEquipExternals) {
|
Thread.sleep(100);
|
DeviceInfo info = new DeviceInfo();
|
info.setDeviceId(ardEquipExternal.getId());
|
info.setIp(ardEquipExternal.getIp());
|
info.setPort(ardEquipExternal.getPort());
|
info.setUsername(ardEquipExternal.getUsername());
|
info.setPassword(ardEquipExternal.getPassword());
|
logout(info);
|
}
|
} catch (Exception ex) {
|
log.error("登出所有外联设备异常:" + ex.getMessage());
|
}
|
}
|
|
|
/**
|
* 建立布防上传通道,用于传输数据
|
*
|
* @param lUserID 唯一标识符
|
* @param lAlarmHandle 报警处理器
|
*/
|
public static int setupAlarmChan(String deviceIpPort, int lUserID, int lAlarmHandle) {
|
// 根据设备注册生成的lUserID建立布防的上传通道,即数据的上传通道
|
if (lUserID == -1) {
|
log.error("请先注册");
|
return lUserID;
|
}
|
if (lAlarmHandle < 0) {
|
// 设备尚未布防,需要先进行布防
|
if (fMSFCallBack_V31 == null) {
|
fMSFCallBack_V31 = new FMSGCallBack();
|
if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V50(0, fMSFCallBack_V31, null)) {
|
log.error("设置回调函数失败!错误码==========》" + hCNetSDK.NET_DVR_GetLastError());
|
}
|
}
|
// 这里需要对设备进行相应的参数设置,不设置或设置错误都会导致设备注册失败
|
HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
|
m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
|
// 智能交通布防优先级:0 - 一等级(高),1 - 二等级(中),2 - 三等级(低)
|
m_strAlarmInfo.byLevel = 0;
|
// 智能交通报警信息上传类型:0 - 老报警信息(NET_DVR_PLATE_RESULT), 1 - 新报警信息(NET_ITS_PLATE_RESULT)
|
m_strAlarmInfo.byAlarmInfoType = 1;
|
// 布防类型(仅针对门禁主机、人证设备):0 - 客户端布防(会断网续传),1 - 实时布防(只上传实时数据)
|
m_strAlarmInfo.byDeployType = 1;
|
//人脸报警信息类型:1- 人脸侦测报警 0- 人脸抓拍报警
|
m_strAlarmInfo.byFaceAlarmDetection = 0;
|
//报警图片数据类型,按位表示:
|
//bit0- 人脸抓拍(报警类型为COMM_UPLOAD_FACESNAP_RESULT)中图片数据上传类型:0- 二进制传输,1- URL传输
|
//bit1- EVENT_JSON(报警类型为COMM_VCA_ALARM)中图片数据上传类型:0- 二进制传输,1- URL传输
|
//bit2- 人脸比对(报警类型为COMM_SNAP_MATCH_ALARM)中图片数据上传类型:0- 二进制传输,1- URL传输
|
m_strAlarmInfo.byAlarmTypeURL = 0;
|
m_strAlarmInfo.write();
|
// 布防成功,返回布防成功的数据传输通道号
|
lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, m_strAlarmInfo);
|
if (lAlarmHandle == -1) {
|
log.error("设备【" + deviceIpPort + "】布防失败,错误码==========》" + hCNetSDK.NET_DVR_GetLastError());
|
} else {
|
log.debug("设备【" + deviceIpPort + "】布防成功");
|
}
|
}
|
return lAlarmHandle;
|
}
|
|
/**
|
* 注销
|
*
|
* @param lUserID 设备注册成功唯一标识符
|
*/
|
public static void logout(int lUserID) {
|
// 注销
|
hCNetSDK.NET_DVR_Logout(lUserID);
|
// 释放sdk资源
|
hCNetSDK.NET_DVR_Cleanup();
|
}
|
|
/**
|
* 抓图
|
*
|
* @param cmd 抓图命令
|
*/
|
public static String picCutCate(CameraCmd cmd) {
|
String cameraId = cmd.getCameraId();
|
Integer channelNum = cmd.getChannelNum();
|
if (!GlobalVariable.loginMap.containsKey(cameraId)) {
|
return "";
|
}
|
Integer userId = GlobalVariable.loginMap.get(cameraId);
|
//图片信息
|
HCNetSDK.NET_DVR_JPEGPARA jpeg = new HCNetSDK.NET_DVR_JPEGPARA();
|
//设置图片分辨率
|
//图片尺寸:0-CIF(352*288/352*240),1-QCIF(176*144/176*120),2-4CIF(704*576/704*480)或D1(720*576/720*486),3-UXGA(1600*1200),
|
// 4-SVGA(800*600),5-HD720P(1280*720),6-VGA(640*480),7-XVGA(1280*960),8-HD900P(1600*900),9-HD1080P(1920*1080),10-2560*1920,
|
// 11-1600*304,12-2048*1536,13-2448*2048,14-2448*1200,15-2448*800,16-XGA(1024*768),17-SXGA(1280*1024),18-WD1(960*576/960*480),
|
// 19-1080I(1920*1080),20-576*576,21-1536*1536,22-1920*1920,23-320*240,24-720*720,25-1024*768,26-1280*1280,27-1600*600,
|
// 28-2048*768,29-160*120,75-336*256,78-384*256,79-384*216,80-320*256,82-320*192,83-512*384,127-480*272,128-512*272, 161-288*320,
|
// 162-144*176,163-480*640,164-240*320,165-120*160,166-576*720,167-720*1280,168-576*960,180-180*240, 181-360*480, 182-540*720,
|
// 183-720*960, 184-960*1280, 185-1080*1440, 500-384*288, 0xff-Auto(使用当前码流分辨率)
|
jpeg.wPicSize = 0;
|
//设置图片质量:0-最好,1-较好,2-一般
|
jpeg.wPicQuality = 0;
|
IntByReference a = new IntByReference();
|
//设置图片大小
|
ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
|
// 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
|
// log.debug("-----------这里开始封装 NET_DVR_CaptureJPEGPicture_NEW---------");
|
boolean is = hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, channelNum, jpeg, jpegBuffer, 1024 * 1024, a);
|
//log.debug("-----------这里开始图片存入内存----------" + is);
|
if (is) {
|
// log.debug("hksdk(抓图)-结果状态值(0表示成功):" + hCNetSDK.NET_DVR_GetLastError());
|
byte[] array = jpegBuffer.array();
|
//存储到minio
|
|
String ContentType = "image/JPEG";
|
InputStream input = new ByteArrayInputStream(array);
|
String url = "";
|
try {
|
boolean b = MinioUtil.uploadObject(cmd.getBucketName(), cmd.getObjectName(), input, input.available(), ContentType);
|
if (b) {
|
url = MinioUtil.getBucketObjectUrl(cmd.getBucketName(), cmd.getObjectName());
|
// log.debug("上传文件成功!" + url);
|
}
|
} catch (Exception ex) {
|
log.error("上传文件异常:" + ex.getMessage());
|
}
|
return url;
|
} else {
|
int code = hCNetSDK.NET_DVR_GetLastError();
|
log.debug("抓图失败,请稍后重试" + code);
|
return "";
|
}
|
}
|
|
/**
|
* 获取防区名称
|
* 通道号==防区号 从0开始
|
* 刘苏义
|
* 2023/7/6 10:48
|
*/
|
public static String getDefenseZoneName(CameraCmd cmd) {
|
String name = "";
|
try {
|
String cameraId = cmd.getCameraId();
|
Integer channelNum = cmd.getWZoneIndex();//通道号==防区号
|
if (!GlobalVariable.loginMap.containsKey(cameraId)) {
|
return name;
|
}
|
Integer userId = GlobalVariable.loginMap.get(cameraId);
|
|
HCNetSDK.NET_DVR_ALARMIN_PARAM netDvrAlarminParam = new HCNetSDK.NET_DVR_ALARMIN_PARAM();
|
Pointer point = netDvrAlarminParam.getPointer();
|
IntByReference ibrBytesReturned = new IntByReference();
|
netDvrAlarminParam.write();
|
boolean b = hCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_ALARMIN_PARAM, channelNum, point, netDvrAlarminParam.size(), ibrBytesReturned);
|
if (b) {
|
netDvrAlarminParam.read();
|
name = ByteUtils.bytesToStringZh(netDvrAlarminParam.byName);
|
} else {
|
int error = hCNetSDK.NET_DVR_GetLastError();
|
log.info("获取防区名称失败:" + error);
|
}
|
} catch (Exception ex) {
|
log.error("获取防区名称异常:" + ex.getMessage());
|
}
|
return name;
|
}
|
|
//获取IP通道
|
public static void getIPChannelInfo(String deviceId, int iUserID) {
|
try {
|
GlobalVariable.deviceChanMap.remove(deviceId);
|
List<ChannelInfo> channelInfoList = new ArrayList<>();
|
int chanNum = 64;
|
IntByReference ibrBytesReturned = new IntByReference(0);//获取IP接入配置参数
|
HCNetSDK.NET_DVR_IPPARACFG_V40 m_strIpparaCfg = new HCNetSDK.NET_DVR_IPPARACFG_V40();
|
m_strIpparaCfg.write();
|
//lpIpParaConfig 接收数据的缓冲指针
|
Pointer lpIpParaConfig = m_strIpparaCfg.getPointer();
|
boolean bRet = hCNetSDK.NET_DVR_GetDVRConfig(iUserID, HCNetSDK.NET_DVR_GET_IPPARACFG_V40, 0, lpIpParaConfig, m_strIpparaCfg.size(), ibrBytesReturned);
|
m_strIpparaCfg.read();
|
//log.debug("起始数字通道号:" + m_strIpparaCfg.dwStartDChan);
|
for (int iChannum = 0; iChannum < chanNum; iChannum++) {
|
int channum = iChannum + m_strIpparaCfg.dwStartDChan;
|
HCNetSDK.NET_DVR_PICCFG_V40 strPicCfg = new HCNetSDK.NET_DVR_PICCFG_V40();
|
strPicCfg.dwSize = strPicCfg.size();
|
strPicCfg.write();
|
Pointer pStrPicCfg = strPicCfg.getPointer();
|
NativeLong lChannel = new NativeLong(channum);
|
IntByReference pInt = new IntByReference(0);
|
boolean b_GetPicCfg = hCNetSDK.NET_DVR_GetDVRConfig(iUserID, HCNetSDK.NET_DVR_GET_PICCFG_V40, lChannel.intValue(),
|
pStrPicCfg, strPicCfg.size(), pInt);
|
// if (b_GetPicCfg == false) {
|
// System.out.println("获取图像参数失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
|
// }
|
strPicCfg.read();
|
m_strIpparaCfg.struStreamMode[iChannum].read();
|
if (m_strIpparaCfg.struStreamMode[iChannum].byGetStreamType == 0) {
|
m_strIpparaCfg.struStreamMode[iChannum].uGetStream.setType(HCNetSDK.NET_DVR_IPCHANINFO.class);
|
m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.read();
|
|
//log.debug("--------------第" + (iChannum + 1) + "个通道------------------");
|
int channel = m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPID + m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPIDHigh * 256;
|
//log.debug("channel:" + channel);
|
if (channel > 0) {
|
//log.debug("name: " + new String(strPicCfg.sChanName, "GBK").trim());
|
//log.debug("ip: " + new String(m_strIpparaCfg.struIPDevInfo[channel - 1].struIP.sIpV4).trim());
|
//log.debug("port: " + m_strIpparaCfg.struIPDevInfo[channel - 1].wDVRPort);
|
String name = new String(strPicCfg.sChanName, "GBK").trim();
|
String ip = new String(m_strIpparaCfg.struIPDevInfo[channel - 1].struIP.sIpV4).trim();
|
int port = m_strIpparaCfg.struIPDevInfo[channel - 1].wDVRPort;
|
ChannelInfo channelInfo = new ChannelInfo();
|
channelInfo.setIp(ip);
|
channelInfo.setPort(port);
|
channelInfo.setName(name);
|
channelInfoList.add(channelInfo);
|
}
|
if (m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byEnable == 1) {
|
//log.debug("IP通道" + channum + "在线");
|
} else {
|
//log.debug("IP通道" + channum + "不在线");
|
}
|
}
|
}
|
if (channelInfoList.size() > 0) {
|
GlobalVariable.deviceChanMap.put(deviceId, channelInfoList);
|
}
|
} catch (Exception ex) {
|
log.error("获取IP通道异常:" + ex.getMessage());
|
}
|
}
|
|
|
|
}
|