在网上搜索了大量资料,都没有找到适合自己的。网上大部分都是对海康SDK的讲解,或者是图形化界面的运行。涉及到web开发时,也是通过WebComponents.exe进行开发,与我所需的功能均不一致,所以还是打算自己尝试并最终上线使用。这里进行一下整理,希望对其他人也能有所帮助。
首先步骤都是一样的,到官网下载自己需要的SDK开发包,官网地址如下,自取。
https://www.hikvision.com/cn/download_61.html
我这里用到的是linux64,将/lib和/lib/HCNetSDKCom下自己需要的.so库文件到拷贝到linux /usr/lib/目录下,如果不知道哪些是自己需要的,全丢进去就好。
在官方的LinuxJavaDemo中,提供了两个jar包,自行导入并build path即可。由于我的项目通过maven进行管理,所以需要导入依赖。
jna.jar在仓库中可以搜索到,选择sun公司的最新版本导入即可。examples.jar仓库中是搜不到的,所以要加到自己的仓库中并增加依赖,这一步需要自行完成。
下面才开始进入开发阶段。官方的demo中有一个至关重要的文件,对于初次进行海康SDK二次开发的人来说,是非常有帮助的。HCNetSDK.java中涵盖了海康大部分的SDK及相应的Structure,后续的开发主要基于这些接口和Structure来完成。
同时需要注意的是,要弄清楚自己的开发平台,当基于linux进行开发时,该类需要继承Library来对.so库文件进行加载,而当基于windows进行开发时要继承StdCallLibrary对.dll进行加载,否则可能会出现部分SDK不可用或内存字段赋值错误的情况。Native.loadLibrary用来指定库文件路径及转换之后的类。windows下可以指定全路径。
下面直接放上我自己写的sdk文件,由于我的项目中只需要实现视频的查找、下载等相关功能,所以代码中的接口及Structure肯定是没有demo中全的。只是为了给大家提供个思路和方向,毕竟coder最擅长的就是根据API码砖了。这里有一点需要注意的是,在实际的项目开发中,demo中HCNetSDK.java是不能拿来直接用的,编译器会报错,根据报错提示,需要将为override的方法补全。主要涉及到的方法是父类Structure中的public List getFieldOrder();方法,该方法是为了以正确的顺序返回此Structure的字段名称,因此override此方法时,需要根据当前Structure的字段来完成,否则会报错。
import com.sun.jna.*;
import com.sun.jna.examples.win32.W32API.HWND;
import com.sun.jna.ptr.IntByReference;
import java.util.Arrays;
import java.util.List;
/**
* SDK接口说明
*
* @author DiCaprito
*/
public interface HcNetSdk extends Library {
HcNetSdk INSTANCE = (HcNetSdk) Native.loadLibrary(
"hcnetsdk",
HcNetSdk.class);
/**
* 正在查找文件
*/
public static final int NET_DVR_IS_FINDING = 1002;
/**
* 用户名长度
*/
public static final int NAME_LEN = 32;
/**
* 密码长度
*/
public static final int PWD_LEN = 16;
/**
* 序列号长度
*/
public static final int SERIAL_NUM_LEN = 48;
/**
* 最大32个模拟通道
*/
public static final int MAX_ANALOG_CHAN_NUM = 32;
/**
* 允许接入的最大IP设备数
*/
public static final int MAX_IP_DEVICE = 32;
/**
* 允许加入的最多IP通道数
*/
public static final int MAX_IP_CHANNEL = 32;
/**
* 最大支持的通道数 最大模拟加上最大IP支持64
*/
public static final int MAX_CHAN_NUM_V30 = (MAX_ANALOG_CHAN_NUM + MAX_IP_CHANNEL);
/**
* 开始播放
*/
public static final int NET_DVR_PLAY_START = 1;
/**
* 获取文件回放的进度
*/
public static final int NET_DVR_PLAY_GET_POS = 13;
/**
* 获取IP接入配置信息
*/
public static final int NET_DVR_GET_IPPARACFG = 1048;
/**
* 用户交互时异常
*/
public static final int EXCEPTION_EXCHANGE = 0x8000;
/**
* 校时结构参数
*/
public static class NET_DVR_TIME extends Structure {
/**
* 年
*/
public int dwYear;
/**
* 月
*/
public int dwMonth;
/**
* 日
*/
public int dwDay;
/**
* 时
*/
public int dwHour;
/**
* 分
*/
public int dwMinute;
/**
* 秒
*/
public int dwSecond;
@Override
public String toString() {
return "NET_DVR_TIME.dwYear: " + dwYear + "\n" + "NET_DVR_TIME.dwMonth: \n" + dwMonth + "\n" + "NET_DVR_TIME.dwDay: \n" + dwDay + "\n" + "NET_DVR_TIME.dwHour: \n" + dwHour + "\n" + "NET_DVR_TIME.dwMinute: \n" + dwMinute + "\n" + "NET_DVR_TIME.dwSecond: \n" + dwSecond;
}
public String toStringTime() {
return String.format("%02d/%02d/%02d%02d:%02d:%02d", dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond);
}
public String toStringTitle() {
return String.format("Time%02d%02d%02d%02d%02d%02d", dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond);
}
@Override
public List<String> getFieldOrder() {
return Arrays.asList("dwYear", "dwMonth", "dwDay", "dwHour", "dwMinute", "dwSecond");
}
}
/**
* ip结构体
*/
public static class NET_DVR_IPADDR extends Structure {
public byte[] sIpV4 = new byte[16];
public byte[] byRes = new byte[128];
@Override
public String toString() {
return "NET_DVR_IPADDR.sIpV4: " + new String(sIpV4) + "\n" + "NET_DVR_IPADDR.byRes: " + new String(byRes) + "\n";
}
@Override
public List<String> getFieldOrder() {
return Arrays.asList("sIpV4", "byRes");
}
}
/**
* IP设备结构
*/
public static class NET_DVR_IPDEVINFO extends Structure {
/**
* 该IP设备是否启用
*/
public int dwEnable;
/**
* 用户名
*/
public byte[] sUserName = new byte[NAME_LEN];
/**
* 密码
*/
public byte[] sPassword = new byte[PWD_LEN];
/**
* IP地址
*/
public NET_DVR_IPADDR struIP = new NET_DVR_IPADDR();
/**
* 端口号