Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录

1.准备工作

  • 1.1. 设备型号
    萤石多功能互联网摄像头 CS-C2C-3B2WFR
  • 1.2. SDK下载
    通过海康威视官网可以下载到最新的Linux下的SDK开发包,分为32位和64位,根据电脑情况选择下载即可。路径如下:
    (1)设备网络SDK_V6.0.2.35(for Linux32)
    http://www1.hikvision.com/cn/download_more_402.html
    (2)设备网络SDK_V6.0.2.35(for Linux64)
    http://www1.hikvision.com/cn/download_more_403.html
  • 1.3 sdk目录结构
    将下载的sdk压缩包进行解压,本人下载的是64位的开发包,目录结构如下:
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第1张图片
    进入LinuxJavaDemo中,目录如下:
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第2张图片
    找到src目录下HCNetSDK.java文件,以及jna.jar和example.jar两个jar包,这几个文件也是需要加载到后面自己创建的java项目中的。
  • 1.4 linux系统下动态链接库文件路径配置
    在《Linux下JavaDemo使用说明.docx》以及《readme.txt》两个文档中介绍了在linux下配置so动态链接库文件路径的几种方式:
    方法一
    在系统的/usr/lib文件中加入你Java工程所需要使用的so文件,然后将HCNetSDKCom文件夹下的组件库也copy到/usr/lib目录
    方法二
    修改etc目录下ld.so.conf文件中的配置。加上你自己的Java工程所需要的so文件的路径。然后调用ldconfig命令使配置生效
    在这里插入图片描述
    方式三
    修改etc目录下profile文件中的配置,将网络SDK各动态库路径加入到LD_LIBRARY_PATH环境变量,然后执行source /etc/profile命令使环境变量生效。
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第3张图片
    我选择了方法三进行配置。

2.代码开发

  • 2.1 新建项目,并添加HCNetSDK.java文件,以及jna.jar和example.jar两个jar包
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第4张图片
  • 2.2 将jna.jar和example.jar两个jar包添加到项目中
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第5张图片
    通过上述几个步骤将第三方的jar包添加到项目中
  • 2.3 修改HCNetSDK.java文件
    Linux系统下使用java语言调用海康威视SDK连接摄像头过程记录_第6张图片
    红框中Native.loadLibrary(“hcnetsdk”,HCNetSDK.class)的第一个参数必须和官方提供的动态链接库文件名一致,且必须要按照1.4小节所述正确配置LD_LIBRARY_PATH,只有这样项目运行的时候可以正确调用libhcnetsdk.so文件。
  • 2.4 LoginService 实现设备的初始化、登录、登出
@Service("loginService")
public class LoginService {

    private final static Logger logger = LoggerFactory.getLogger(LoginService.class);
    private HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo;
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
    boolean initSuc = false;

    @Autowired
    private UserIdMap userIdMap;
    @Autowired
    private Result result;

    LoginService() {
    }

    public Response init() {
        // 初始化SDK
        initSuc = hCNetSDK.NET_DVR_Init();
        if (initSuc == false) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        return result.successed();
    }

    public Response login(String uuid, String ip, Short port, String username, String password) {
        // 用户注册设备
        deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
        NativeLong userID = new NativeLong(-1);
        userID = hCNetSDK.NET_DVR_Login_V30(ip, port, username, password, deviceInfo);
        userIdMap.put(uuid, userID.longValue());
        if (0 != userID.longValue()) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        return result.successed();
    }

    public Response logout(String uuid) {
        long userID = userIdMap.get(uuid);
        // 用户注销
        if (!hCNetSDK.NET_DVR_Logout(new NativeLong(userID))) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        userIdMap.put(uuid, userIdMap.INVALID_USERID);
        return result.successed();
    }
}
  • 2.5 DeployService 主要实现设备的布防/撤防
@Service("deployService")
public class DeployService {
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
    @Autowired
    private FmsgCallBackV31 fmsfCallBackV31;
    @Autowired
    private AlarmHandleMap alarmHandleMap;
    @Autowired
    private UserIdMap userIdMap;
    @Autowired
    private Result result;

    public Response deploy(String uuid) {
        // 注册回调函数,接收设备报警消息等
        Pointer pUser = null;
        if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fmsfCallBackV31, pUser)) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        long userID = userIdMap.get(uuid);
        // 建立报警上传通道,获取报警等信息
        HCNetSDK.NET_DVR_SETUPALARM_PARAM alarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
        alarmInfo.dwSize = alarmInfo.size();
        alarmInfo.byLevel = 1;
        alarmInfo.byAlarmInfoType = 1;
        alarmInfo.byFaceAlarmDetection = 0;
        alarmInfo.write();
        NativeLong alarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(new NativeLong(userID), alarmInfo);
        alarmHandleMap.put(uuid, alarmHandle.longValue());
        if (alarmHandleMap.INVALID_ALARMHANDLE == alarmHandle.intValue()) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        return result.successed();
    }

    public Response unDeploy(String uuid) {
        // 撤销报警上传通道
        long alarmHandle = alarmHandleMap.get(uuid);
        if (!hCNetSDK.NET_DVR_CloseAlarmChan_V30(new NativeLong(alarmHandle))) {
            return result.failed(hCNetSDK.NET_DVR_GetLastError());
        }
        alarmHandleMap.put(uuid, alarmHandleMap.INVALID_ALARMHANDLE);
        return result.successed();
    }
}
  • 2.6 FmsgCallBackV31 回调函数实现,实现报警事件的处理
@Component
public class FmsgCallBackV31 implements HCNetSDK.FMSGCallBack_V31 {
    @Autowired
    private EventMap eventMap;

    public boolean invoke(NativeLong lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer,
                          Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
        return true;
    }

    // 事件转json字符串
    public String eventToJson(String time, String type, String id, int door) {
        Event atd = new Event();
        atd.setId(id);
        atd.setTime(time);
        atd.setType(type);
        atd.setDoor(door);
        ObjectMapper objectMapper = new ObjectMapper();
        String json = null;
        try {
            json = objectMapper.writeValueAsString(atd);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return json;
    }

    public void alarmDataHandle(NativeLong lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        switch (lCommand.intValue()) {
            // 门禁报警
            case HCNetSDK.COMM_ALARM_ACS:
                HCNetSDK.NET_DVR_ACS_ALARM_INFO strAlarmInfo = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
                strAlarmInfo.write();
                Pointer pAlarm = strAlarmInfo.getPointer();
                pAlarm.write(0, pAlarmInfo.getByteArray(0, strAlarmInfo.size()), 0, strAlarmInfo.size());
                strAlarmInfo.read();

                if (HCNetSDK.MAJOR_EVENT == strAlarmInfo.dwMajor) {
                    // 事件类报警
                    switch (strAlarmInfo.dwMinor) {
                        case HCNetSDK.MINOR_FINGERPRINT_COMPARE_PASS:
                            // 指纹比对通过
                        case HCNetSDK.MINOR_FACE_VERIFY_PASS:
                            // 人脸认证通过
                            try {
                                String time = strAlarmInfo.struTime.toStringTime();
                                String id = new String(strAlarmInfo.struAcsEventInfo.byCardNo, "GB2312").trim();
                                String type = eventMap.getEvent(strAlarmInfo.dwMinor);
                                int door = strAlarmInfo.struAcsEventInfo.dwDoorNo;
                                System.out.println("time: "+time+" ,type: "+type+" , id: "+id+" ,door: "+door);//jcs
                                String json = eventToJson(time, type, id, door);
                                System.out.println(json);
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                            break;
                        default:
                            break;
                    }
                }
                break;
            case HCNetSDK.COMM_ALARM_V30:
                HCNetSDK.NET_DVR_ALARMINFO_V30 struAlarmInfo30 = new HCNetSDK.NET_DVR_ALARMINFO_V30();
                struAlarmInfo30.write();
                Pointer pAlarmInfo30 = struAlarmInfo30.getPointer();
                pAlarmInfo30.write(0, pAlarmInfo30.getByteArray(0, struAlarmInfo30.size()), 0, struAlarmInfo30.size());
                struAlarmInfo30.read();
                //报警类型:0-信号量报警,1-硬盘满,2-信号丢失,3-移动侦测,
                // 4-硬盘未格式化,5-读写硬盘出错,6-遮挡报警,7-制式不匹配,
                // 8-非法访问,9-视频信号异常,10-录像/抓图异常,11-智能场景变化,
                // 12-阵列异常,13-前端/录像分辨率不匹配,15-智能侦测,16-POE供电异常,
                // 17-闪光灯异常,18-磁盘满负荷异常报警,19-音频丢失,23-脉冲报警,
                // 24-人脸库硬盘异常,25-人脸库变更,26-人脸库图片变更
                int alarmType = struAlarmInfo30.dwAlarmType;
                switch (alarmType){
                    case 0:
                        System.out.println("信号量报警");
                        break;
                    case 3:
                        System.out.println("移动侦测");
                        break;
                    case 6:
                        System.out.println("遮挡报警");
                        break;
                    default:
                        System.out.println("其他报警");
                        break;
                }
            default:
                break;
        }
    }
}

3 项目打包

因为项目要在linux下运行,所以需要在windows下将项目进行打包,本文将项目打成jar包。接下来介绍一下pom.xml文件中关于打包的配置。

<build>
    <!-- 主要配置:将引用的第三方 jar 包打进生成的 jar 文件的 BOOT-INF/lib 目录中 -->
    <resources>
        <resource>
            <directory>src\main\java\com\test\utils</directory>
            <targetPath>BOOT-INF\lib</targetPath>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <targetPath>.</targetPath>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <!-- 配置加载第三方jar包的目录 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <skip>true</skip>
                <encoding>UTF-8</encoding>
                <compilerArguments>
                    <extdirs>${project.basedir}/src/main/java/com/test/utils</extdirs>
                </compilerArguments>
            </configuration>
        </plugin>
    </plugins>
</build>

通过上述的配置,可以将第三方包(jna\example.jar)打包到jar的BOOT-INF\lib目录下,否则的话打包出来的jar包将缺少这两个重要的文件而导致jar包运行失败。

4.总结

本文主要介绍了如何使用官方提供的linux下的SDK来开发能够在linux系统下运行的java程序,主要包括对sdk目录的介绍,对几个重要文件的说明,linux系统下动态链接库文件路径的配置,以及项目代码的简单说明,希望能够对要做类似工作的朋友提供一定的帮助。

5.下载

Linux下海康威视IPC二次开发资源包
个人实现的IPC设备管理程序

你可能感兴趣的:(java)