SpringBoot集成核康設(shè)備網(wǎng)絡(luò)SDK

SDK介紹

概述

設(shè)備網(wǎng)絡(luò)SDK是基于設(shè)備私有網(wǎng)絡(luò)通信協(xié)議開(kāi)發(fā)的,為嵌入式網(wǎng)絡(luò)硬盤(pán)錄像機(jī)茅郎、NVR际乘、網(wǎng)絡(luò)攝像機(jī)苍匆、網(wǎng)絡(luò)球機(jī)太抓、視頻服務(wù)器绢记、解碼器、報(bào)警主機(jī)毕谴、網(wǎng)絡(luò)存儲(chǔ)等產(chǎn)品服務(wù)的配套模塊成畦,用于遠(yuǎn)程訪問(wèn)和控制設(shè)備軟件的二次開(kāi)發(fā)。

功能

圖像預(yù)覽, 文件回放和下載, 云臺(tái)控制, 布防/撤防, 語(yǔ)音對(duì)講, 日志管理, 解碼卡, 遠(yuǎn)程升級(jí), 遠(yuǎn)程重啟/關(guān)閉, 格式化硬盤(pán), 參數(shù)配置(系統(tǒng)配置, 通道配置, 串口配置, 報(bào)警配置, 用戶配置), 多路解碼器, 智能設(shè)備功能和獲取設(shè)備能力集等涝开。

下載

https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10

image.png

對(duì)接指南

以java為例

由于我司提供的設(shè)備網(wǎng)絡(luò)SDK是封裝的動(dòng)態(tài)鏈接庫(kù)(Windows的dll或者Linux的so),各種開(kāi)發(fā)語(yǔ)言對(duì)接SDK框仔,都是通過(guò)加載動(dòng)態(tài)庫(kù)鏈接舀武,調(diào)用動(dòng)態(tài)庫(kù)中的接口實(shí)現(xiàn)功能模塊對(duì)接,因此离斩,設(shè)備網(wǎng)絡(luò)SDK的對(duì)接不區(qū)分開(kāi)發(fā)語(yǔ)言银舱,而且對(duì)接的流程和對(duì)應(yīng)的接口都是通用的,各種語(yǔ)言調(diào)用動(dòng)態(tài)庫(kù)的方式有所不同跛梗。本文重點(diǎn)介紹java開(kāi)發(fā)語(yǔ)言如何對(duì)接設(shè)備網(wǎng)絡(luò)SDK寻馏。目前我司提供的java語(yǔ)言開(kāi)發(fā)的demo是通過(guò)JNA的方式調(diào)用動(dòng)態(tài)鏈接庫(kù)中的接口,JNA(Java Native Access)框架是SUN公司主導(dǎo)開(kāi)發(fā)的開(kāi)源java框架核偿,是建立在JNI的基礎(chǔ)上的一個(gè)框架诚欠,JNA框架提供了一組java工具類(lèi)用于在運(yùn)行期間動(dòng)態(tài)訪問(wèn)動(dòng)態(tài)鏈接庫(kù)(native library:如Window的dll、Linux的so)漾岳,實(shí)現(xiàn)在java語(yǔ)言中調(diào)用C/C++語(yǔ)言封裝的接口轰绵,java開(kāi)發(fā)人員只需要在一個(gè)java接口中描述目標(biāo)native library的函數(shù)與結(jié)構(gòu),JNA將自動(dòng)實(shí)現(xiàn)Java接口到native function的映射尼荆,而不需要編寫(xiě)任何Native/JNI代碼左腔,大大降低了Java調(diào)用動(dòng)態(tài)鏈接庫(kù)的開(kāi)發(fā)難度。相比于JNI的方式捅儒,JNA大大簡(jiǎn)化了調(diào)用本地方法的過(guò)程液样,使用很方便振亮,基本上不需要脫離Java環(huán)境就可以完成。JNA調(diào)用C/C++的過(guò)程大致如下:

image.png

集成

SpringBoot 項(xiàng)目為例鞭莽,核唬康SDK版本為6.1.9.47,JNA版本為3.0.9撮抓,在windows環(huán)境使用Intellij IDEA 2022.2.3開(kāi)發(fā)

初始化項(xiàng)目

  • 新建 SpringBoot 項(xiàng)目妇斤,版本 2.5.3
  • 添加pom依賴:jna,fastjson2

<dependency>
        <groupId>com.sun.jna</groupId>
        <artifactId>jna</artifactId>
        <version>3.0.9</version>
</dependency>


<dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.20</version>
</dependency>          


  • 將下載下來(lái)的旱ふ康sdk放到項(xiàng)目目錄站超,并根據(jù)操作系統(tǒng)不同分別創(chuàng)建相應(yīng)的文件夾
  • 若出現(xiàn) HCNetSDK.NET_DVR_PREVIEWINFO.HWND找不到引用,可做如下處理:1:在ProjectStructure中引入官方示例代碼中的 examples.jar 乖酬;2:將 HWND 類(lèi)型修改為 int
image.png
  • 設(shè)置一個(gè)喜歡的端口 server.port

初始化SDK

初始化SDK概述

一般的死相,我們希望在程序啟動(dòng)的時(shí)候就初始化sdk。

  • 這里使用了 ApplicationRunner 作為初始化入口咬像,當(dāng)程序啟動(dòng)成功后算撮,將執(zhí)行 Runner 做初始化
  • 為避免初始化sdk對(duì)主線程造成影響,所以 ApplicationRunner 需要放在線程池中 ThreadPoolExecutor县昂,并添加try-catch處理
  • HCNetSDK是SDK示例代碼中提供的一個(gè)對(duì)象肮柜,此對(duì)象繼承Library,負(fù)責(zé)和更底層的C/C++庫(kù)(更底層也許是C寫(xiě)的倒彰,這里不確定)交互审洞,即執(zhí)行 Native 調(diào)用。通過(guò)實(shí)例化此對(duì)象完成sdk依賴庫(kù)的導(dǎo)入待讳,并在后續(xù)業(yè)務(wù)開(kāi)發(fā)中使用此對(duì)象向攝像機(jī)發(fā)布指令芒澜。
  • 涉及多操作系統(tǒng)平臺(tái)的差異性,官方分別提供不同sdk依賴庫(kù)创淡,具體包含:win32痴晦,win64,linux32琳彩,linux64等誊酌,所以當(dāng)初始化SDK的時(shí)候需要根據(jù)當(dāng)前所處環(huán)境不同分別加載不同的依賴庫(kù)文件
  • 上述提到的依賴庫(kù)文件,在windows下就是 dll 后綴文件 汁针, 在 linux 下就是 so 后綴文件
  • 真正執(zhí)行初始化就是調(diào)用 hCNetSDK.NET_DVR_Init() 此方法术辐,并可通過(guò)返回值為 truefalse 判斷初始化是否成功。

新建AppRunner

  • AppRunner 需要實(shí)現(xiàn) ApplicationRunner 接口施无,并將
    AppRunner作為組件放到Spring 容器中管理
  • AppRunner 中注入SdkInitService 辉词,并在run 方法中調(diào)用 SdkInitService 的initSdk 方法實(shí)現(xiàn)SDK的初始化

package com.ramble.hikvisionsdkintegration;
import com.ramble.hikvisionsdkintegration.service.SdkInitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class AppRunner  implements ApplicationRunner {
    @Autowired
    private SdkInitService hksdkInitService;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        hksdkInitService.initSdk();
    }
}


新建SdkInitService

  • 定義一個(gè)公開(kāi)的 hCNetSDK 屬性,類(lèi)型為 HCNetSDK 猾骡,并在構(gòu)造函數(shù)中初始化 hCNetSDK 屬性的值瑞躺,此值需要全局唯一敷搪,這里參照官方代碼做了單例處理。HCNetSDK 是官方提供的一個(gè)接口幢哨,一般的都是直接copy到項(xiàng)目源代碼中赡勘,你會(huì)發(fā)現(xiàn),所有和設(shè)備交互的地方都是通過(guò)這個(gè)接口來(lái)完成的
  • 內(nèi)部定義一個(gè)異忱塘回調(diào)類(lèi)闸与,用來(lái)處理和設(shè)備交互的時(shí)候全局異常的處理
  • 注入 ThreadPoolExecutor 執(zhí)行器,真正的初始化將放到子線程中進(jìn)行
  • 定義 initSdk 方法用來(lái)執(zhí)行初始化
  • 需要注意的是岸售,構(gòu)造函數(shù)中為 hCNetSDK 屬性初始化值践樱,僅僅只是為了將 sdk 所需的依賴庫(kù)文件 加載到運(yùn)行時(shí)中,并沒(méi)有真正的做初始化SDK的工作
  • 需要重點(diǎn)關(guān)注OSUtils中的代碼凸丸,加載依賴庫(kù)文件的前提是找到對(duì)應(yīng)的庫(kù)文件拷邢,的操作是在 getLoadLibrary 方法中管理的,這里編寫(xiě)的代碼需要和部署時(shí)候選擇的部署方式對(duì)應(yīng)屎慢,否則可能會(huì)出現(xiàn)在windows中開(kāi)發(fā)正常瞭稼,部署到linux 中就報(bào)異常的問(wèn)題

SdkInitService:


package com.ramble.hikvisionsdkintegration.service;
import com.ramble.hikvisionsdkintegration.sdklib.HCNetSDK;
import com.ramble.hikvisionsdkintegration.task.InitSdkTask;
import com.ramble.hikvisionsdkintegration.util.OSUtils;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Component
public class SdkInitService {
    public static HCNetSDK hCNetSDK = null;
    static FExceptionCallBack_Imp fExceptionCallBack;
    static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack {
        public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {
            System.out.println("異常事件類(lèi)型:" + dwType);
            return;
        }
    }
    public SdkInitService() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                try {
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(OSUtils.getLoadLibrary(), HCNetSDK.class);
                } catch (Exception ex) {
                    log.error("SdkInitService-init-hCNetSDK-error");
                }
            }
        }
    }
    @Autowired
    private ThreadPoolExecutor executor;
    public void initSdk() {
        log.info("HKSDKInitService-init-coming");
        executor.execute(new InitSdkTask());
    }
}

OSUtils:


package com.ramble.hikvisionsdkintegration.util;
import com.sun.jna.Platform;
import lombok.extern.slf4j.Slf4j;
import java.io.File;

@Slf4j
public class OSUtils {
    // 獲取操作平臺(tái)信息
    public static String getOsPrefix() {
        String arch = System.getProperty("os.arch").toLowerCase();
        final String name = System.getProperty("os.name");
        String osPrefix;
        if (Platform.isWindows()) {
            if ("i386".equals(arch)) {
                arch = "x86";
            }
            osPrefix = "win32-" + arch;
        } else if (Platform.isLinux()) {
            if ("x86".equals(arch)) {
                arch = "i386";
            } else if ("x86_64".equals(arch)) {
                arch = "amd64";
            }
            osPrefix = "linux-" + arch;
        } else {
            osPrefix = name.toLowerCase();
            if ("x86".equals(arch)) {
                arch = "i386";
            }
            if ("x86_64".equals(arch)) {
                arch = "amd64";
            }
            int space = osPrefix.indexOf(" ");
            if (space != -1) {
                osPrefix = osPrefix.substring(0, space);
            }
            osPrefix += "-" + arch;
        }
        return osPrefix;
    }
    public static String getOsName() {
        String osName = "";
        String osPrefix = getOsPrefix();
        if (osPrefix.toLowerCase().startsWith("win32-x86")
                || osPrefix.toLowerCase().startsWith("win32-amd64")) {
            osName = "win";
        } else if (osPrefix.toLowerCase().startsWith("linux-i386")
                || osPrefix.toLowerCase().startsWith("linux-amd64")) {
            osName = "linux";
        }
        return osName;
    }
    /**
     * 獲取庫(kù)文件
     * 區(qū)分win、linux
     *
     * @return
     */
    public static String getLoadLibrary() {
        if (isChecking()) {
            return null;
        }
        String userDir = System.getProperty("user.dir");
        log.info("getLoadLibrary-userDir={}", userDir);
        String loadLibrary = "";
        String library = "";
        String osPrefix = getOsPrefix();
        if (osPrefix.toLowerCase().startsWith("win32-x86")) {
            loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin32" + File.separator;
            library = "HCNetSDK.dll";
        } else if (osPrefix.toLowerCase().startsWith("win32-amd64")) {
            loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin64" + File.separator;
            library = "HCNetSDK.dll";
        } else if (osPrefix.toLowerCase().startsWith("linux-i386")) {
            //同 linux-amd64
            loadLibrary = "";
            library = "libhcnetsdk.so";
        } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) {
            //方式一:使用系統(tǒng)默認(rèn)的加載庫(kù)路徑腻惠,在系統(tǒng)的/usr/lib文件中加入你Java工程所需要使用的so文件环肘,然后將HCNetSDKCom文件夾下的組件庫(kù)也復(fù)制到/usr/lib目錄,HCNetSDKCom文件夾中的組件庫(kù)不要隨意更換路徑妖枚。CentOS 64位需拷貝到/usr/lib64下廷臼。
            //針對(duì)方式一,前綴就是絕對(duì)路徑
            //loadLibrary = "/usr/lib64/lib/hkliblinux64/";
            //方式二:配置LD_LIBRARY_PATH環(huán)境變量加載庫(kù)文件绝页;配置/etc/ld.so.conf,加上你自己的Java工程所需要的so文件的路徑
            //針對(duì)方式二寂恬,無(wú)需添加前綴续誉,程序會(huì)從linux系統(tǒng)的so共享庫(kù)中查找libhcnetsdk.so
            loadLibrary = "";
            library = "libhcnetsdk.so";
        }
        log.info("================= Load library Path :{} ==================", loadLibrary + library);
        return loadLibrary + library;
    }
    private static boolean checking = false;
    public static void setChecking() {
        checking = true;
    }
    public static void clearChecking() {
        checking = false;
    }
    public static boolean isChecking() {
        return checking;
    }
}


新建InitSdkTask

  • 此類(lèi)實(shí)現(xiàn) Runnable 接口,并重寫(xiě)run方法初肉。
  • 新建一個(gè)私有屬性 hCNetSDK 并賦值為 SdkInitService.hCNetSDK 酷鸦,因?yàn)槌跏蓟枰玫?HCNetSDK 這個(gè)對(duì)象和設(shè)備交互,所以初始化前必須確保此對(duì)象已經(jīng)創(chuàng)建牙咏,本例中臼隔,程序在執(zhí)行 SdkInitService 構(gòu)造函數(shù)的時(shí)候初始化了 HCNetSDK 對(duì)象,并放到一個(gè)全局靜態(tài)變量中
  • 其實(shí)也可以不新建私有屬性 hCNetSDK 妄壶,在需要用到此對(duì)象的地方 使用 SdkInitService.hCNetSDK 的方式獲取也可以
  • 通過(guò)調(diào)用 hCNetSDK.NET_DVR_Init 方法執(zhí)行初始化摔握,并可以通過(guò)返回值確定是否初始化成功,初始化成功后丁寄,將可以調(diào)用業(yè)務(wù)接口向設(shè)備發(fā)送指令氨淌。
  • NET_DVR_SetConnectTime泊愧,NET_DVR_SetReconnect 是可選的,并不會(huì)對(duì)初始化SDK本身造成影響盛正。
  • 為了避免對(duì)主程序造成影響删咱,初始化代碼將需要做 try - catch 處理

InitSdkTask:


package com.ramble.hikvisionsdkintegration.task;
import com.ramble.hikvisionsdkintegration.sdklib.HCNetSDK;
import com.ramble.hikvisionsdkintegration.service.SdkInitService;
import com.ramble.hikvisionsdkintegration.util.OSUtils;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;

@Slf4j
public class InitSdkTask implements Runnable {
    /**
     * 裝配 sdk 所需依賴
     */
    private static HCNetSDK hCNetSDK = SdkInitService.hCNetSDK;
    @Override
    public void run() {
        try {
            if (Objects.equals(OSUtils.getOsName(), "linux")) {
                log.info("InitSdk-is-linux");
                String userDir = System.getProperty("user.dir");
                log.info("InitSdk-userDir={}", userDir);
                String osPrefix = OSUtils.getOsPrefix();
                if (osPrefix.toLowerCase().startsWith("linux-i386")) {
                    HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
                    HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
                    //這里是庫(kù)的絕對(duì)路徑,請(qǐng)根據(jù)實(shí)際情況修改豪筝,注意改路徑必須有訪問(wèn)權(quán)限
                    //linux 下痰滋, 庫(kù)加載參考:OSUtils.getLoadLibrary()
                    String strPath1 = System.getProperty("user.dir") + "/hkliblinux32/libcrypto.so.1.1";
                    String strPath2 = System.getProperty("user.dir") + "/hkliblinux32/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());
                    //linux 下, 庫(kù)加載參考:OSUtils.getLoadLibrary()
                    String strPathCom = System.getProperty("user.dir") + "/hkliblinux32/HCNetSDKCom/";
                    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());
                } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) {
                    HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
                    HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
                    //這里是庫(kù)的絕對(duì)路徑续崖,請(qǐng)根據(jù)實(shí)際情況修改敲街,注意改路徑必須有訪問(wèn)權(quán)限
                    //linux 下, 庫(kù)加載參考:OSUtils.getLoadLibrary()
                    String strPath1 = System.getProperty("user.dir") + "/hkliblinux64/libcrypto.so.1.1";
                    String strPath2 = System.getProperty("user.dir") + "/hkliblinux64/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") + "/hkliblinux64/HCNetSDKCom/";
                    //linux 下袜刷, 庫(kù)加載參考:OSUtils.getLoadLibrary()
                    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());
                } else {
                    log.info("osPrefix={}", osPrefix);
                }
            }
            //初始化sdk
            boolean isOk = hCNetSDK.NET_DVR_Init();
            hCNetSDK.NET_DVR_SetConnectTime(10, 1);
            hCNetSDK.NET_DVR_SetReconnect(100, true);
            if (!isOk) {
                log.error("=================== InitSDK init fail ===================");
            } else {
                log.info("============== InitSDK init success ====================");
            }
        } catch (Exception e) {
            log.error("InitSDK-error,e={}", e.getMessage());
            e.printStackTrace();
        }
    }
}


新建 HCNetSDK

直接從官方示例代碼中copy過(guò)來(lái)即可

調(diào)用業(yè)務(wù)接口

  • 新建一個(gè)controller 聪富,嘗試調(diào)用 獲取SDK狀態(tài) 的接口。
  • 調(diào)用所有的業(yè)務(wù)接口之前都需要先登錄

package com.ramble.hikvisionsdkintegration.controller;
import com.alibaba.fastjson2.JSON;
import com.ramble.hikvisionsdkintegration.dto.GlobalResponseEntity;
import com.ramble.hikvisionsdkintegration.sdklib.HCNetSDK;
import com.ramble.hikvisionsdkintegration.service.SdkInitService;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/test")
public class TestController {
    private static String m_sDeviceIP = "192.168.1.142";
    private static String m_sUsername = "xxx";
    private static String m_sPassword = "xxx";
    
    /**
     * 獲取sdk狀態(tài)
     *
     * @return {@link GlobalResponseEntity}<{@link String}>
     * 返回值舉例:{"success":true,"code":"000000","message":"request successfully",
     * "data":"{\"dwRes\":[0,0,0,0,0,0,0,0,0,0],\"dwTotalAlarmChanNum\":0,\"dwTotalBroadCastNum\":0,\"dwTotalFileSearchNum\":0,\"dwTotalFormatNum\":0,
     * \"dwTotalLogSearchNum\":0,\"dwTotalLoginNum\":1,\"dwTotalPlayBackNum\":0,\"dwTotalRealPlayNum\":0,\"dwTotalSerialNum\":0,\"dwTotalUpgradeNum\":0,
     * \"dwTotalVoiceComNum\":0,\"autoRead\":true,\"autoWrite\":true,\"pointer\":{\"size\":84,\"valid\":true}}"}
     */
     
    @GetMapping("/state")
    public GlobalResponseEntity<String> getSdkState() {
        //登錄
        Integer userId = login();
        log.info("userId={}", userId);
        HCNetSDK.NET_DVR_SDKSTATE sdkState = new HCNetSDK.NET_DVR_SDKSTATE();
        //獲取當(dāng)前SDK狀態(tài)信息
        boolean result = SdkInitService.hCNetSDK.NET_DVR_GetSDKState(sdkState);
        if (result) {
            sdkState.read();
            String s = JSON.toJSONString(sdkState);
            return GlobalResponseEntity.success(s);
        } else {
            int error = SdkInitService.hCNetSDK.NET_DVR_GetLastError();
            return GlobalResponseEntity.error("獲取失敗著蟹,錯(cuò)誤碼為:" + error);
        }
    }
    
    
    private Integer login() {
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//設(shè)備登錄信息
        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 = Short.valueOf("8000");
        m_strLoginInfo.bUseAsynLogin = false; //是否異步登錄:0- 否墩蔓,1- 是
        m_strLoginInfo.write();
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//設(shè)備信息
        int loginHandler = SdkInitService.hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (loginHandler == -1) {
            int errorCode = SdkInitService.hCNetSDK.NET_DVR_GetLastError();
            IntByReference errorInt = new IntByReference(errorCode);
            log.error("[HK] login fail errorCode:{}, errMsg:{}", errorCode, SdkInitService.hCNetSDK.NET_DVR_GetErrorMsg(errorInt));
            return null;
        } else {
            return loginHandler;
        }
    }
}


部署

拷貝so庫(kù)文件到部署目錄

所有廠家的所有版本sdk庫(kù)文件均維護(hù)在項(xiàng)目源代碼中,需要將linux庫(kù)文件so文件拷貝到部署根目錄萧豆,和jar文件同級(jí)

追加環(huán)境變量

通過(guò)配置 LD_LIBRARY_PATH 環(huán)境變量加載庫(kù)文件奸披,打開(kāi)系統(tǒng)的 /etc/profile 配置文件,在最后追加so庫(kù)文件所在目錄:


export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/app/jars/hkliblinux64:/home/app/jars/hkliblinux64/HCNetSDKCom

如上所示:
● 32位就追加 hkliblinux32 目錄涮雷,64位就追加 hkliblinux64 目錄
● 不要忘記 HCNetSDKCom 目錄也需要配置阵面,因?yàn)槔锩嬉灿衧o庫(kù)文件。
執(zhí)行source 命令洪鸭,讓配置生效:


source   /etc/profile

追加so庫(kù)加載路徑

打開(kāi) /etc/ld.so.conf配置文件样刷,追加so庫(kù)文件所在目錄


/home/app/jars/hkliblinux64
/home/app/jars/hkliblinux64/HCNetSDKCom

如上所示:
● 32位就追加 hkliblinux32 目錄,64位就追加 hkliblinux64 目錄览爵。
● 不要忘記 HCNetSDKCom 目錄也需要配置置鼻,因?yàn)槔锩嬉灿衧o庫(kù)文件。

執(zhí)行 ldconfig 命令蜓竹,讓配置生效:


ldconfig

驗(yàn)證SDK初始化是否成功

一般來(lái)說(shuō)箕母,可以在程序初始化SDK的時(shí)候添加日志,通過(guò)日志輸出判斷是否初始化成功俱济。

代碼

https://gitee.com/naylor_personal/ramble-spring-boot/tree/master/hikvision-sdk-integration

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嘶是,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛛碌,更是在濱河造成了極大的恐慌聂喇,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件左医,死亡現(xiàn)場(chǎng)離奇詭異授帕,居然都是意外死亡同木,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)跛十,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)彤路,“玉大人,你說(shuō)我怎么就攤上這事芥映≈拮穑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵奈偏,是天一觀的道長(zhǎng)坞嘀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)惊来,這世上最難降的妖魔是什么丽涩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮裁蚁,結(jié)果婚禮上矢渊,老公的妹妹穿的比我還像新娘。我一直安慰自己枉证,他們只是感情好矮男,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著室谚,像睡著了一般毡鉴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秒赤,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天猪瞬,我揣著相機(jī)與錄音,去河邊找鬼入篮。 笑死撑螺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崎弃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼含潘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼饲做!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起遏弱,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盆均,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后漱逸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體泪姨,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡游沿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肮砾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诀黍。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仗处,靈堂內(nèi)的尸體忽然破棺而出眯勾,到底是詐尸還是另有隱情,我是刑警寧澤婆誓,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布吃环,位于F島的核電站,受9級(jí)特大地震影響洋幻,放射性物質(zhì)發(fā)生泄漏郁轻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一文留、第九天 我趴在偏房一處隱蔽的房頂上張望好唯。 院中可真熱鬧,春花似錦厂庇、人聲如沸渠啊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)替蛉。三九已至,卻和暖如春拄氯,著一層夾襖步出監(jiān)牢的瞬間躲查,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工译柏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镣煮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓鄙麦,卻偏偏與公主長(zhǎng)得像典唇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胯府,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容