[Java]海康人脸识别门禁(明眸)以人为中心SDK用法举例

2021-07-18 4626点热度 0人点赞 0条评论

之前的文章介绍了海康人脸识别门禁(明眸)以卡为中心SDK用法举例,详见:https://blog.terrynow.com/2021/07/16/java-hikvision-face-recognition-entrance-guard-sdk-based-on-card-example/

一般用的较多的,可能是以人为中心,海康的自己的后台也是以用户为中心的(先添加employeeNo工号,然后在工号的基础上添加指纹、人脸等)

下面是我整理的以人为中心的SDK封装好的工具类,有需要的供参考,实现的功能有:

  • 登录设备
  • 注销
  • 获取事件列表
  • 查询人员(用户)信息(列表)
  • 删除用户
  • 查询人脸数据
  • 添加用户信息
  • 更新用户信息
  • 添加人脸数据
  • 删除人脸数据
  • 远程控门

我用到的HCNetSDK.java,这个只要在官方下载到的SDK的DEMO里下载就可以了。

添加依赖

  • 海康SKD使用到了jna,不过是挺老的版本3.0.9,这个可以在maven库里面找到,也可以手动引入官方的jar,这里我用maven引入
  • 还需要org.json
  • 还用到了log4j,使用其他log框架的,自行修改
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20200518</version>
</dependency>

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>

工具类

HCNetDeviceUtil.java

import com.icisclab.hc.lib.HCNetSDK;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @author Terry E-mail: yaoxinghuo at 126 dot com
 * @date 2020-11-7 15:14
 * @description 设备网络SDK编程指南(明眸-以人为中心).pdf
 */
public class HCNetDeviceUtil {

    private static final Log log = LogFactory.getLog(HCNetDeviceUtil.class);

    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;

    HCNetSDK hcNetSDK = HCNetSDK.INSTANCE;
    private int userId;

    /**
     * 登录设备
     */
    public void loginDevice(String ip, int port, String userName, String password) throws Exception {
        //注册
        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(ip.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, ip.length());

        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(userName.getBytes(), 0, m_strLoginInfo.sUserName, 0, userName.length());

        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(password.getBytes(), 0, m_strLoginInfo.sPassword, 0, password.length());

        m_strLoginInfo.wPort = (short) port;
        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是
        m_strLoginInfo.write();

        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
        int lUserID = hcNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID == -1) {
            throw new Exception("登录失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        }
        this.userId = lUserID;
//        else
//        {
//            System.out.println("登录成功!");
////            iCharEncodeType = m_strDeviceInfo.byCharEncodeType;
//        }
    }

//    public String capture(String path) throws Exception {
//        File file = new File(path);
//        if (!file.exists()) {
//            file.mkdirs();
//        }
//        String fileName = path + System.currentTimeMillis() + ".jpg";
//        HCNetSDK.NET_DVR_JPEGPARA picPara = new HCNetSDK.NET_DVR_JPEGPARA();
//        System.out.println("******" + hcNetSDK.NET_DVR_GetLastError() + "*********");
//        picPara.wPicSize = 0;
//        picPara.wPicQuality = 0;
//        hcNetSDK.NET_DVR_GetDVRConfig(this.userId, 0, 0, null, 0, null);
//        String picPath = fileName;
//        boolean ff = hcNetSDK.NET_DVR_CaptureJPEGPicture(this.userId, 1, picPara, picPath);
//        System.out.println("******" + ff + hcNetSDK.NET_DVR_GetLastError() + "*********");
//        if (!ff) {
//            throw new Exception();
//        }
//        return fileName;
//    }

    /**
     * 注销,用完后记得注销,要不然登录的太多,后续登录会报错
     */
    public void logout() {
        hcNetSDK.NET_DVR_Logout_V30(this.userId);
    }

    /**
     * 获取设备能力集
     */
    public JSONObject getAbility() throws Exception {
        JSONObject jsonObject = new JSONObject();
        String strURL = "GET /ISAPI/AccessControl/UserInfo/capabilities?format=json";
        HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);
        System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length());
        ptrUrl.write();

        //获取能力集时输入参数为空即可
        /*HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN);
        ptrInBuffer.read();
        String strInbuffer = "";
        ptrInBuffer.byValue = strInbuffer.getBytes();
        ptrInBuffer.write();
        */

        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        struXMLInput.dwSize = struXMLInput.size();
        struXMLInput.lpRequestUrl = ptrUrl.getPointer();
        struXMLInput.dwRequestUrlLen = ptrUrl.byValue.length;
        struXMLInput.lpInBuffer = null;//ptrInBuffer.getPointer();
        struXMLInput.dwInBufferSize = 0;//ptrInBuffer.byValue.length;
        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(this.userId, struXMLInput, struXMLOutput)) {
            int iErr = hcNetSDK.NET_DVR_GetLastError();
            throw new Exception("NET_DVR_STDXMLConfig失败,错误号:" + iErr);
        } else {
            struXMLOutput.read();
            ptrOutByte.read();
            ptrStatusByte.read();
            String strOut = new String(ptrOutByte.byValue).trim();
//            System.out.println("获取设备能力集输出结果:" + strOutXML);
            String strStatus = new String(ptrStatusByte.byValue).trim();
            log.info("获取设备能力集返回状态:" + strStatus);
            jsonObject = new JSONObject(strOut);
            return jsonObject;
        }
    }

    /**
     * 去掉空白这种特殊字符
     */
    private String hcBytesToString(byte[] bytes) {
        return new String(bytes).replace("\u0000", "");
    }

    /**
     * 获取事件列表
     */
    public JSONArray getDeviceEvents(Date start, Date end) throws Exception {
        JSONArray jsonArray = new JSONArray();

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(start);
        HCNetSDK.NET_DVR_TIME startTime = new HCNetSDK.NET_DVR_TIME();
        startTime.dwYear = startCalendar.get(Calendar.YEAR); // 年
        startTime.dwMonth = startCalendar.get(Calendar.MONTH) + 1; // 月
        startTime.dwDay = startCalendar.get(Calendar.DAY_OF_MONTH);
        startTime.dwHour = startCalendar.get(Calendar.HOUR_OF_DAY); // 时
        startTime.dwMinute = startCalendar.get(Calendar.MINUTE); // 分
        startTime.dwSecond = startCalendar.get(Calendar.SECOND); // 秒

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(end);
        HCNetSDK.NET_DVR_TIME endTime = new HCNetSDK.NET_DVR_TIME();
        endTime.dwYear = endCalendar.get(Calendar.YEAR); // 年
        endTime.dwMonth = endCalendar.get(Calendar.MONTH) + 1; // 月
        endTime.dwDay = endCalendar.get(Calendar.DAY_OF_MONTH);
        endTime.dwHour = endCalendar.get(Calendar.HOUR_OF_DAY); // 时
        endTime.dwMinute = endCalendar.get(Calendar.MINUTE); // 分
        endTime.dwSecond = endCalendar.get(Calendar.SECOND); // 秒

        // 调用获取设备事件长连接
        HCNetSDK.NET_DVR_ACS_EVENT_COND_V50 struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND_V50();
        struAcsEventCond.read();
        struAcsEventCond.dwSize = struAcsEventCond.size();
        struAcsEventCond.dwMajor = 5;// 5代表event事件
//        struAcsEventCond.dwMinor = 0x4b;// 代表刷脸成功
        struAcsEventCond.dwMinor = 0;// 代表全部
        struAcsEventCond.struStartTime = startTime;// ****必须要
        struAcsEventCond.struEndTime = endTime;// ***必须要
        struAcsEventCond.write();
        Pointer ptrStruEventCond = struAcsEventCond.getPointer();
        int lHandle = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, HCNetSDK.NET_DVR_GET_ACS_EVENT, ptrStruEventCond,
                struAcsEventCond.size(), null, null);
        if (lHandle == -1) {
            throw new Exception("建立获取设备事件长连接失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
        }
//        log.info("建立获取设备事件连接成功!" + lHandle);
        // 获取设备详细事件开始
        HCNetSDK.NET_DVR_ACS_EVENT_CFG_V50 struEventCFG = new HCNetSDK.NET_DVR_ACS_EVENT_CFG_V50();
        struEventCFG.read();
        struEventCFG.dwSize = struEventCFG.size();
        struEventCFG.write();
        int dwState = -1;
        while (true) {
            dwState = hcNetSDK.NET_DVR_GetNextRemoteConfig(lHandle, struEventCFG.getPointer(), struEventCFG.size());
            struEventCFG.read();
            if (dwState == -1) {
                log.warn("NET_DVR_GetNextRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            } else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {
                // 配置等待
//                log.info("==========配置等待==============");
                try {
                    Thread.sleep(10);
                } catch (Exception ignored) {
                }
            } else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {
                // 获取事件失败
                log.warn("===============获取设备事件失败=======================");
                break;

            } else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_EXCEPTION) {
                // 获取事件异常
                log.warn("===============获取设备事件异常=======================");
                break;
            } else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {
                // 获取设备事件成功
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("employeeNo", hcBytesToString(struEventCFG.struAcsEventInfo.byEmployeeNo));
                jsonObject.put("cardNo", hcBytesToString(struEventCFG.struAcsEventInfo.byCardNo));
                //MINOR_LEGAL_CARD_PASS	0x01	合法卡认证通过
                //MINOR_CARD_AND_PSW_PASS	0x02	刷卡加密码认证通过
                //MINOR_CARD_AND_PSW_FAIL	0x03	刷卡加密码认证失败
                //MINOR_CARD_AND_PSW_TIMEOUT	0x04	数卡加密码认证超时
                //MINOR_CARD_AND_PSW_OVER_TIME	0x05	刷卡加密码超次
                //MINOR_CARD_NO_RIGHT	0x06	未分配权限
                //MINOR_CARD_INVALID_PERIOD	0x07	无效时段
                //MINOR_CARD_OUT_OF_DATE	0x08	卡号过期
                //MINOR_INVALID_CARD	0x09	无此卡号
                //MINOR_ANTI_SNEAK_FAIL	0x0a	反潜回认证失败
                //MINOR_INTERLOCK_DOOR_NOT_CLOSE	0x0b	互锁门未关闭
                //MINOR_NOT_BELONG_MULTI_GROUP	0x0c	卡不属于多重认证群组
                //MINOR_INVALID_MULTI_VERIFY_PERIOD	0x0d	卡不在多重认证时间段内
                //MINOR_MULTI_VERIFY_SUPER_RIGHT_FAIL	0x0e	多重认证模式超级权限认证失败
                //MINOR_MULTI_VERIFY_REMOTE_RIGHT_FAIL	0x0f	多重认证模式远程认证失败
                //MINOR_MULTI_VERIFY_SUCCESS	0x10	多重认证成功
                //MINOR_LEADER_CARD_OPEN_BEGIN	0x11	首卡开门开始
                //MINOR_LEADER_CARD_OPEN_END	0x12	首卡开门结束
                //MINOR_ALWAYS_OPEN_BEGIN	0x13	常开状态开始
                //MINOR_ALWAYS_OPEN_END	0x14	常开状态结束
                //MINOR_LOCK_OPEN	0x15	门锁打开
                //MINOR_LOCK_CLOSE	0x16	门锁关闭
                //MINOR_DOOR_BUTTON_PRESS	0x17	开门按钮打开
                //MINOR_DOOR_BUTTON_RELEASE	0x18	开门按钮放开
                //MINOR_DOOR_OPEN_NORMAL	0x19	正常开门(门磁)
                //MINOR_DOOR_CLOSE_NORMAL	0x1a	正常关门(门磁)
                //MINOR_DOOR_OPEN_ABNORMAL	0x1b	门异常打开(门磁)
                //MINOR_DOOR_OPEN_TIMEOUT	0x1c	门打开超时(门磁)
                //MINOR_ALARMOUT_ON	0x1d	报警输出打开
                //MINOR_ALARMOUT_OFF	0x1e	报警输出关闭
                //MINOR_ALWAYS_CLOSE_BEGIN	0x1f	常关状态开始
                //MINOR_ALWAYS_CLOSE_END	0x20	常关状态结束
                //MINOR_MULTI_VERIFY_NEED_REMOTE_OPEN	0x21	多重多重认证需要远程开门
                //MINOR_MULTI_VERIFY_SUPERPASSWD_VERIFY_SUCCESS	0x22	多重认证超级密码认证成功事件
                //MINOR_MULTI_VERIFY_REPEAT_VERIFY	0x23	多重认证重复认证事件
                //MINOR_MULTI_VERIFY_TIMEOUT	0x24	多重认证重复认证事件
                //MINOR_DOORBELL_RINGING	0x25	门铃响
                //MINOR_FINGERPRINT_COMPARE_PASS	0x26	指纹比对通过
                //MINOR_FINGERPRINT_COMPARE_FAIL	0x27	指纹比对失败
                //MINOR_CARD_FINGERPRINT_VERIFY_PASS	0x28	刷卡加指纹认证通过
                //MINOR_CARD_FINGERPRINT_VERIFY_FAIL	0x29	刷卡加指纹认证失败
                //MINOR_CARD_FINGERPRINT_VERIFY_TIMEOUT	0x2a	刷卡加指纹认证超时
                //MINOR_CARD_FINGERPRINT_PASSWD_VERIFY_PASS	0x2b	刷卡加指纹加密码认证通过
                //MINOR_CARD_FINGERPRINT_PASSWD_VERIFY_FAIL	0x2c	刷卡加指纹加密码认证失败
                //MINOR_CARD_FINGERPRINT_PASSWD_VERIFY_TIMEOUT	0x2d	刷卡加指纹加密码认证超时
                //MINOR_FINGERPRINT_PASSWD_VERIFY_PASS	0x2e	指纹加密码认证通过
                //MINOR_FINGERPRINT_PASSWD_VERIFY_FAIL	0x2f	指纹加密码认证失败
                //MINOR_FINGERPRINT_PASSWD_VERIFY_TIMEOUT	0x30	指纹加密码认证超时
                //MINOR_FINGERPRINT_INEXISTENCE	0x31	指纹不存在
                //MINOR_CARD_PLATFORM_VERIFY	0x32	刷卡平台认证
                //MINOR_CALL_CENTER	0x33	呼叫中心事件
                //MINOR_FIRE_RELAY_TURN_ON_DOOR_ALWAYS_OPEN	0x34	消防继电器导通触发门常开
                //MINOR_FIRE_RELAY_RECOVER_DOOR_RECOVER_NORMAL	0x35	消防继电器恢复门恢复正常
                //MINOR_FACE_AND_FP_VERIFY_PASS	0x36	人脸加指纹认证通过
                //MINOR_FACE_AND_FP_VERIFY_FAIL	0x37	人脸加指纹认证失败
                //MINOR_FACE_AND_FP_VERIFY_TIMEOUT	0x38	人脸加指纹认证超时
                //MINOR_FACE_AND_PW_VERIFY_PASS	0x39	人脸加密码认证通过
                //MINOR_FACE_AND_PW_VERIFY_FAIL	0x3a	人脸加密码认证失败
                //MINOR_FACE_AND_PW_VERIFY_TIMEOUT	0x3b	人脸加密码认证超时
                //MINOR_FACE_AND_CARD_VERIFY_PASS	0x3c	人脸加刷卡认证通过
                //MINOR_FACE_AND_CARD_VERIFY_FAIL	0x3d	人脸加刷卡认证失败
                //MINOR_FACE_AND_CARD_VERIFY_TIMEOUT	0x3e	人脸加刷卡认证超时
                //MINOR_FACE_AND_PW_AND_FP_VERIFY_PASS	0x3f	人脸加密码加指纹认证通过
                //MINOR_FACE_AND_PW_AND_FP_VERIFY_FAIL	0x40	人脸加密码加指纹认证失败
                //MINOR_FACE_AND_PW_AND_FP_VERIFY_TIMEOUT	0x41	人脸加密码加指纹认证超时
                //MINOR_FACE_CARD_AND_FP_VERIFY_PASS	0x42	人脸加刷卡加指纹认证通过
                //MINOR_FACE_CARD_AND_FP_VERIFY_FAIL	0x43	人脸加刷卡加指纹认证失败
                //MINOR_FACE_CARD_AND_FP_VERIFY_TIMEOUT	0x44	人脸加刷卡加指纹认证超时
                //MINOR_EMPLOYEENO_AND_FP_VERIFY_PASS	0x45	工号加指纹认证通过
                //MINOR_EMPLOYEENO_AND_FP_VERIFY_FAIL	0x46	工号加指纹认证失败
                //MINOR_EMPLOYEENO_AND_FP_VERIFY_TIMEOUT	0x47	工号加指纹认证超时
                //MINOR_EMPLOYEENO_AND_FP_AND_PW_VERIFY_PASS	0x48	工号加指纹加密码认证通过
                //MINOR_EMPLOYEENO_AND_FP_AND_PW_VERIFY_FAIL	0x49	工号加指纹加密码认证失败
                //MINOR_EMPLOYEENO_AND_FP_AND_PW_VERIFY_TIMEOUT	0x4a	工号加指纹加密码认证超时
                //MINOR_FACE_VERIFY_PASS	0x4b	人脸认证通过
                //MINOR_FACE_VERIFY_FAIL	0x4c	人脸认证失败
                //MINOR_EMPLOYEENO_AND_FACE_VERIFY_PASS	0x4d	工号加人脸认证通过
                //MINOR_EMPLOYEENO_AND_FACE_VERIFY_FAIL	0x4e	工号加人脸认证失败
                //MINOR_EMPLOYEENO_AND_FACE_VERIFY_TIMEOUT	0x4f	工号加人脸认证超时
                //MINOR_FACE_RECOGNIZE_FAIL	0x50	人脸识别失败
                //MINOR_FIRSTCARD_AUTHORIZE_BEGIN	0x51	首卡授权开始
                //MINOR_FIRSTCARD_AUTHORIZE_END	0x52	首卡授权结束
                //MINOR_DOORLOCK_INPUT_SHORT_CIRCUIT	0x53	门锁输入短路报警
                //MINOR_DOORLOCK_INPUT_BROKEN_CIRCUIT	0x54	门锁输入断路报警
                //MINOR_DOORLOCK_INPUT_EXCEPTION	0x55	门锁输入异常报警
                //MINOR_DOORCONTACT_INPUT_SHORT_CIRCUIT	0x56	门磁输入短路报警
                //MINOR_DOORCONTACT_INPUT_BROKEN_CIRCUIT	0x57	门磁输入断路报警
                //MINOR_DOORCONTACT_INPUT_EXCEPTION	0x58	门磁输入异常报警
                //MINOR_OPENBUTTON_INPUT_SHORT_CIRCUIT	0x59	开门按钮输入短路报警
                //MINOR_OPENBUTTON_INPUT_BROKEN_CIRCUIT	0x5a	开门按钮输入断路报警
                //MINOR_OPENBUTTON_INPUT_EXCEPTION	0x5b	开门按钮输入异常报警
                //MINOR_DOORLOCK_OPEN_EXCEPTION	0x5c	门锁异常打开
                //MINOR_DOORLOCK_OPEN_TIMEOUT	0x5d	门锁打开超时
                //MINOR_FIRSTCARD_OPEN_WITHOUT_AUTHORIZE	0x5e	首卡未授权开门失败
                //MINOR_CALL_LADDER_RELAY_BREAK	0x5f	呼梯继电器断开
                //MINOR_CALL_LADDER_RELAY_CLOSE	0x60	呼梯继电器闭合
                //MINOR_AUTO_KEY_RELAY_BREAK	0x61	自动按键继电器断开
                //MINOR_AUTO_KEY_RELAY_CLOSE	0x62	自动按键继电器闭合
                //MINOR_KEY_CONTROL_RELAY_BREAK	0x63	按键梯控继电器断开
                //MINOR_KEY_CONTROL_RELAY_CLOSE	0x64	按键梯控继电器闭合
                //MINOR_EMPLOYEENO_AND_PW_PASS	0x65	工号加密码认证通过
                //MINOR_EMPLOYEENO_AND_PW_FAIL	0x66	工号加密码认证失败
                //MINOR_EMPLOYEENO_AND_PW_TIMEOUT	0x67	工号加密码认证超时
                //MINOR_HUMAN_DETECT_FAIL	0x68	真人检测失败
                //MINOR_PEOPLE_AND_ID_CARD_COMPARE_PASS	0x69	人证比对通过
                //MINOR_PEOPLE_AND_ID_CARD_COMPARE_FAIL	0x70	人证比对失败
                //MINOR_CERTIFICATE_BLACK_LIST	0x71	黑名单事件
                //MINOR_LEGAL_MESSAGE	0x72	合法短信
                //MINOR_ILLEGAL_MESSAGE	0x73	非法短信
                //MINOR_MAC_DETECT	0x74	MAC侦测
                //MINOR_DOOR_OPEN_OR_DORMANT_FAIL	0x75	门状态常闭或休眠状态认证失败
                //MINOR_AUTH_PLAN_DORMANT_FAIL	0x76	认证计划休眠模式认证失败
                //MINOR_AUTH_PLAN_DORMANT_FAIL	0x76	认证计划休眠模式认证失败
                //MINOR_CARD_ENCRYPT_VERIFY_FAIL	0x77	卡加密校验失败
                //MINOR_SUBMARINEBACK_REPLY_FAIL	0x78	反潜回服务器应答失败
                //MINOR_TRAILING	0x85	尾随通行
                //MINOR_REVERSE_ACCESS	0x86	反向闯入
                //MINOR_FORCE_ACCESS	0x87	外力冲撞
                //MINOR_CLIMBING_OVER_GATE	0x88	翻越
                //MINOR_PASSING_TIMEOUT	0x89	通行超时
                //MINOR_INTRUSION_ALARM	0x8a	误闯报警
                //MINOR_FREE_GATE_PASS_NOT_AUTH	0x8b	闸机自由通行时未认证通过
                //MINOR_DROP_ARM_BLOCK	0x8c	摆臂被阻挡
                //MINOR_DROP_ARM_BLOCK_RESUME	0x8d	摆臂阻挡消除
                //MINOR_LOCAL_FACE_MODELING_FAIL	0x8e	设备升级本地人脸建模失败
                //MINOR_STAY_EVENT	0x8f	逗留事件
                //MINOR_PASSWORD_MISMATCH	0x97	密码不匹配
                //MINOR_EMPLOYEE_NO_NOT_EXIST	0x98	工号不存在
                //MINOR_COMBINED_VERIFY_PASS	0x99	组合认证通过
                //MINOR_COMBINED_VERIFY_TIMEOUT	0x9a	组合认证超时
                //MINOR_VERIFY_MODE_MISMATCH	0x9b	认证方式不匹配
                jsonObject.put("minor", struEventCFG.dwMinor);
                jsonObject.put("time", formatTime(struEventCFG.struTime));
                jsonArray.put(jsonObject);
            } else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FINISH) {
                // 获取设备事件信息完成
                log.info("=============获取设备事件完成================");
                break;
            }
        }
        return jsonArray;
    }

    /**
     * 查询人员信息(列表)
     *
     * @param start 分页用,起始位置
     * @param limit 分页用,限制每页多少个用户
     * @param employeeNos 如果参数为空,就查询全部人员信息
     */
    public JSONObject searchUserInfo(int start, int limit, String... employeeNos) throws Exception {
        JSONObject jsonObject = new JSONObject();

        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);    //数组
        String strInBuffer = "POST /ISAPI/AccessControl/UserInfo/Search?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();

        int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, 2550/*NET_DVR_JSON_CONFIG*/, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            throw new Exception("SearchUserInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        } else {
            //组装查询的JSON报文,这边查询的是所有的卡
            JSONObject jsonSearchCond = new JSONObject();

            //如果需要查询指定的工号人员信息
            if (employeeNos.length > 0) {
                JSONArray employeeArray = new JSONArray();
                for (String employeeNo : employeeNos) {
                    employeeArray.put(new JSONObject().put("employeeNo", employeeNo));
                }
                jsonSearchCond.put("EmployeeNoList", employeeArray);
            }

            jsonSearchCond.put("searchID", "123e4567-e89b-12d3-a456-426655440000");
            jsonSearchCond.put("searchResultPosition", start);
            jsonSearchCond.put("maxResults", limit);

            String strInbuff = new JSONObject().put("UserInfoSearchCond", jsonSearchCond).toString();
//            log.info("查询人员的json报文:" + strInbuff);

            //把string传递到Byte数组中,后续用.getPointer()方法传入指针地址中。
            HCNetSDK.BYTE_ARRAY ptrInbuff = new HCNetSDK.BYTE_ARRAY(strInbuff.length());
            System.arraycopy(strInbuff.getBytes(), 0, ptrInbuff.byValue, 0, strInbuff.length());
            ptrInbuff.write();

            //定义接收结果的结构体
            HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(10 * 1024);

            IntByReference pInt = new IntByReference(0);

            while (true) {
                int dwState = hcNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrInbuff.getPointer(), strInbuff.length(), ptrOutuff.getPointer(), 10 * 1024, pInt);
                System.out.println(dwState);
                if (dwState == -1) {
                    log.error("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {
                    log.info("配置等待");
                    try {
                        Thread.sleep(10);
                    } catch (Exception ignored) {
                    }
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                    log.warn("查询人员失败");
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                    log.warn("查询人员异常");
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
                    ptrOutuff.read();

                    jsonObject = new JSONObject(new String(ptrOutuff.byValue).trim()).getJSONObject("UserInfoSearch");
//                    System.out.println("查询人员成功, json:" + new String(ptrOutuff.byValue).trim());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                    log.info("获取人员完成");
                    break;
                }
            }

            if (!hcNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                log.error("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            }
            return jsonObject;
        }

    }

    /**
     * 删除用户
     * @param employeeNo 工号
     */
    public void delUserInfo(String employeeNo) throws Exception {
        String strURL = "PUT /ISAPI/AccessControl/UserInfo/Delete?format=json";
        HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);
        System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length());
        ptrUrl.write();

        //输入删除条件
        HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN);
        ptrInBuffer.read();
        String strInbuffer = "{\"UserInfoDelCond\":{\"EmployeeNoList\":[{\"employeeNo\":\"" + employeeNo + "\"}]}}";
        ptrInBuffer.byValue = strInbuffer.getBytes();
        ptrInBuffer.write();

        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        struXMLInput.dwSize = struXMLInput.size();
        struXMLInput.lpRequestUrl = ptrUrl.getPointer();
        struXMLInput.dwRequestUrlLen = ptrUrl.byValue.length;
        struXMLInput.lpInBuffer = ptrInBuffer.getPointer();
        struXMLInput.dwInBufferSize = ptrInBuffer.byValue.length;
        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(this.userId, struXMLInput, struXMLOutput)) {
            int iErr = hcNetSDK.NET_DVR_GetLastError();
            throw new Exception("NET_DVR_STDXMLConfig失败,错误号:" + iErr);
        } else {
            struXMLOutput.read();
            ptrOutByte.read();
            ptrStatusByte.read();
            String strOutXML = new String(ptrOutByte.byValue).trim();
            log.warn("删除人员输出结果:" + strOutXML);
            String strStatus = new String(ptrStatusByte.byValue).trim();
            log.warn("删除人员返回状态:" + strStatus);
        }
    }

    /**
     * 查询人脸数据
     * @param employeeNo 工号
     * @return 返回bytes[]
     */
    public byte[] searchFaceInfo(String employeeNo) throws Exception {
        byte[] bytes = null;
        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);    //数组
        String strInBuffer = "POST /ISAPI/Intelligent/FDLib/FDSearch?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();

        int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, 2552/*NET_DVR_FACE_DATA_SEARCH*/, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            throw new Exception("SearchFaceInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        } else {
//            System.out.println("SearchFaceInfo NET_DVR_StartRemoteConfig成功!");

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("searchResultPosition", 0);
            jsonObject.put("maxResults", 1);
            jsonObject.put("faceLibType", "blackFD");
            jsonObject.put("FDID", "1");
            jsonObject.put("FPID", employeeNo);//人脸关联的工号,同下发人员时的employeeNo字段

            String strInbuff = jsonObject.toString();
//            log.info("查询人脸的json报文:" + strInbuff);

            //把string传递到Byte数组中,后续用.getPointer()方法传入指针地址中。
            HCNetSDK.BYTE_ARRAY ptrInbuff = new HCNetSDK.BYTE_ARRAY(strInbuff.length());
            System.arraycopy(strInbuff.getBytes(), 0, ptrInbuff.byValue, 0, strInbuff.length());
            ptrInbuff.write();

            HCNetSDK.NET_DVR_JSON_DATA_CFG m_struJsonData = new HCNetSDK.NET_DVR_JSON_DATA_CFG();
            m_struJsonData.write();

            IntByReference pInt = new IntByReference(0);

            while (true) {
                int dwState = hcNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrInbuff.getPointer(), strInbuff.length(), m_struJsonData.getPointer(), m_struJsonData.size(), pInt);
                m_struJsonData.read();
//                System.out.println(dwState);
                if (dwState == -1) {
                    log.error("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {
                    log.info("配置等待");
                    try {
                        Thread.sleep(10);
                    } catch (Exception ignored) {
                    }
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                    log.warn("查询人脸失败");
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                    log.warn("查询人脸异常");
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
                    log.info("查询人脸成功");

                    //解析JSON字符串
                    HCNetSDK.BYTE_ARRAY pJsonData = new HCNetSDK.BYTE_ARRAY(m_struJsonData.dwJsonDataSize);
                    pJsonData.write();
                    Pointer pPlateInfo = pJsonData.getPointer();
                    pPlateInfo.write(0, m_struJsonData.lpJsonData.getByteArray(0, pJsonData.size()), 0, pJsonData.size());
                    pJsonData.read();
                    String strResult = new String(pJsonData.byValue).trim();
//                    log.info("strResult:" + strResult);
                    JSONObject jsonResult = new JSONObject(strResult);

                    int numOfMatches = jsonResult.optInt("numOfMatches");
                    if (numOfMatches != 0) {//确认有人脸
//                        JSONArray MatchList = jsonResult.getJSONArray("MatchList");
//                        JSONObject MatchList_1 = MatchList.optJSONObject(0);
//                        String FPID = MatchList_1.getString("FPID"); //获取json中人脸关联的工号

                        //将字节写入文件
                        long offset = 0;
                        ByteBuffer buffers = m_struJsonData.lpPicData.getByteBuffer(offset, m_struJsonData.dwPicDataSize);
                        bytes = new byte[m_struJsonData.dwPicDataSize];
                        buffers.rewind();
                        buffers.get(bytes);
                    }
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                    log.info("获取人脸完成");
                    break;
                }
            }
            if (!hcNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            }

        }
        return bytes;

    }

    private String formatTime(HCNetSDK.NET_DVR_TIME_EX ex) {
        if (ex == null) {
            return "";
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, ex.wYear);
        calendar.set(Calendar.MONTH, ex.byMonth - 1);
        calendar.set(Calendar.DAY_OF_MONTH, ex.byDay);
        calendar.set(Calendar.HOUR_OF_DAY, ex.byHour);
        calendar.set(Calendar.MINUTE, ex.byMinute);
        calendar.set(Calendar.SECOND, ex.bySecond);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }

    private String formatTime(HCNetSDK.NET_DVR_TIME ex) {
        if (ex == null) {
            return "";
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, ex.dwYear);
        calendar.set(Calendar.MONTH, ex.dwMonth - 1);
        calendar.set(Calendar.DAY_OF_MONTH, ex.dwDay);
        calendar.set(Calendar.HOUR_OF_DAY, ex.dwHour);
        calendar.set(Calendar.MINUTE, ex.dwMinute);
        calendar.set(Calendar.SECOND, ex.dwSecond);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }

    /**
     * 更新用户信息
     * @param employeeNo 工号
     * @param employeeName 姓名
     * @param password 用户密码,经测试,只能是4-8位纯数字
     * @param start 用户有效期开始
     * @param end 用户有效期结束
     */
    public void updateUser(String employeeNo, String employeeName, String password, Date start, Date end) throws Exception {
        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);    //数组
        String strInBuffer = "PUT /ISAPI/AccessControl/UserInfo/Modify?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();

        int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, 2550/*NET_DVR_JSON_CONFIG*/, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            throw new Exception("ModifyUserInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        } else {
//            System.out.println("UpdateUserInfo NET_DVR_StartRemoteConfig 成功!");
            byte[] name = employeeName.getBytes(StandardCharsets.UTF_8); //根据iCharEncodeType判断,如果iCharEncodeType返回6,则是UTF-8编码。
            //如果是0或者1或者2,则是GBK编码

            //将中文字符编码之后用数组拷贝的方式,避免因为编码导致的长度问题
            String strInBuffer1 = "{\"UserInfo\":{\"Valid\":{\"beginTime\":\""
                    + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(start)
                    + "\",\"enable\":true,\"endTime\":\"" +
                    new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(end)
                    + "\"},\"checkUser\":false,\"doorRight\":\"1\",\"RightPlan\":[{\"doorNo\": 1,\"planTemplateNo\": \"1\"}],\"employeeNo\":\""
                    + employeeNo + "\",\"floorNumber\":1,\"maxOpenDoorTime\":0,\"name\":\"";
            String strInBuffer2 = "\",\"openDelayEnabled\":false,\"password\":\""+password+"\",\"roomNumber\":1,\"userType\":\"normal\"}}";
            int iStringSize = name.length + strInBuffer1.length() + strInBuffer2.length();

            HCNetSDK.BYTE_ARRAY ptrByte = new HCNetSDK.BYTE_ARRAY(iStringSize);
            System.arraycopy(strInBuffer1.getBytes(), 0, ptrByte.byValue, 0, strInBuffer1.length());
            System.arraycopy(name, 0, ptrByte.byValue, strInBuffer1.length(), name.length);
            System.arraycopy(strInBuffer2.getBytes(), 0, ptrByte.byValue, strInBuffer1.length() + name.length, strInBuffer2.length());
            ptrByte.write();

//            System.out.println("修改人员JSON数据:" + new String(ptrByte.byValue));

            HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);

            IntByReference pInt = new IntByReference(0);
            while (true) {
                int dwState = hcNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrByte.getPointer(), iStringSize, ptrOutuff.getPointer(), 1024, pInt);
                //读取返回的json并解析
                ptrOutuff.read();
                String strResult = new String(ptrOutuff.byValue).trim();
//                System.out.println("dwState:" + dwState + ",strResult:" + strResult);

                JSONObject jsonResult = new JSONObject(strResult);
                int statusCode = jsonResult.getInt("statusCode");
//                String statusString = jsonResult.getString("statusString");

                if (dwState == -1) {
                    log.error("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {
                    log.info("配置等待");
                    Thread.sleep(10);
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                    log.error("修改人员失败, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                    log.error("修改人员异常, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文
                    if (statusCode != 1) {
                        log.warn("修改人员成功,但是有异常情况:" + jsonResult.toString());
                    } else {
                        log.info("修改人员成功: json retun:" + jsonResult.toString());
                    }
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                    //下发人员时:dwState其实不会走到这里,因为设备不知道我们会下发多少个人,所以长连接需要我们主动关闭
                    log.info("修改人员完成");
                    break;
                }
            }
            if (!hcNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                log.error("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            }
        }
    }

    /**
     * 新增用户信息
     * @param employeeNo 工号
     * @param employeeName 姓名
     * @param password 用户密码,经测试,只能是4-8位纯数字
     * @param start 用户有效期开始
     * @param end 用户有效期结束
     */
    public void addUser(String employeeNo, String employeeName, String password, Date start, Date end) throws Exception {
        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);    //数组
        String strInBuffer = "POST /ISAPI/AccessControl/UserInfo/Record?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();

        int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, 2550/*NET_DVR_JSON_CONFIG*/, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            throw new Exception("AddUserInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        }

        byte[] name = employeeName.getBytes(StandardCharsets.UTF_8); //根据iCharEncodeType判断,如果iCharEncodeType返回6,则是UTF-8编码。
        //如果是0或者1或者2,则是GBK编码

        //将中文字符编码之后用数组拷贝的方式,避免因为编码导致的长度问题
        String strInBuffer1 = "{\"UserInfo\":{\"Valid\":{\"beginTime\":\""
                + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(start)
                + "\",\"enable\":true,\"endTime\":\"" +
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(end)
                + "\"},\"checkUser\":false,\"doorRight\":\"1\",\"RightPlan\":[{\"doorNo\": 1,\"planTemplateNo\": \"1\"}],\"employeeNo\":\""
                + employeeNo + "\",\"floorNumber\":1,\"maxOpenDoorTime\":0,\"name\":\"";
        String strInBuffer2 = "\",\"openDelayEnabled\":false,\"password\":\""+password+"\",\"roomNumber\":1,\"userType\":\"normal\"}}";
        int iStringSize = name.length + strInBuffer1.length() + strInBuffer2.length();

        HCNetSDK.BYTE_ARRAY ptrByte = new HCNetSDK.BYTE_ARRAY(iStringSize);
        System.arraycopy(strInBuffer1.getBytes(), 0, ptrByte.byValue, 0, strInBuffer1.length());
        System.arraycopy(name, 0, ptrByte.byValue, strInBuffer1.length(), name.length);
        System.arraycopy(strInBuffer2.getBytes(), 0, ptrByte.byValue, strInBuffer1.length() + name.length, strInBuffer2.length());
        ptrByte.write();

        System.out.println(new String(ptrByte.byValue));

        HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);

        IntByReference pInt = new IntByReference(0);
        while (true) {
            int dwState = hcNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrByte.getPointer(), iStringSize, ptrOutuff.getPointer(), 1024, pInt);
            //读取返回的json并解析
            ptrOutuff.read();
            String strResult = new String(ptrOutuff.byValue).trim();
//            System.out.println("dwState:" + dwState + ",strResult:" + strResult);

            JSONObject jsonResult = new JSONObject(strResult);
            int statusCode = jsonResult.getInt("statusCode");
//            String statusString = jsonResult.getString("statusString");

            if (dwState == -1) {
                log.error("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
                break;
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEEDWAIT) {
                log.info("配置等待");
                try {
                    Thread.sleep(10);
                } catch (Exception ignored) {
                }
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                log.error("下发人员失败, json return:" + jsonResult.toString());
                break;
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                log.error("下发人员异常, json return:" + jsonResult.toString());
                break;
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文
                if (statusCode != 1) {
                    log.warn("下发人员成功,但是有异常情况:" + jsonResult.toString());
                } else {
                    log.info("下发人员成功: json return:" + jsonResult.toString());
                }
                break;
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                //下发人员时:dwState其实不会走到这里,因为设备不知道我们会下发多少个人,所以长连接需要我们主动关闭
                log.info("下发人员完成");
                break;
            }
        }
        if (!hcNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
            log.warn("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
        }

    }

    /**
     * 添加人脸数据
     * @param employeeNo 工号
     * @param faceBytes 人脸的bytes[],不能超过200KB
     */
    public void addFace(String employeeNo, byte[] faceBytes) throws Exception {
        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);    //数组
        String strInBuffer = "POST /ISAPI/Intelligent/FDLib/FaceDataRecord?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();

        int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(this.userId, 2551/*NET_DVR_FACE_DATA_RECORD*/, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            throw new Exception("Addface NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
        } else {
//            System.out.println("Addface NET_DVR_StartRemoteConfig 成功!");

            //批量下发多个人脸(不同工号)
            HCNetSDK.NET_DVR_JSON_DATA_CFG struAddFaceDataCfg = new HCNetSDK.NET_DVR_JSON_DATA_CFG();

            struAddFaceDataCfg.read();

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("faceLibType", "blackFD");
            jsonObject.put("FDID", "1");
            jsonObject.put("FPID", employeeNo);//人脸下发关联的工号

            String strJsonData = jsonObject.toString();
            log.info("下发人脸的json报文:" + strJsonData);

            System.arraycopy(strJsonData.getBytes(), 0, ptrByteArray.byValue, 0, strJsonData.length());//字符串拷贝到数组中
            ptrByteArray.write();

            struAddFaceDataCfg.dwSize = struAddFaceDataCfg.size();
            struAddFaceDataCfg.lpJsonData = ptrByteArray.getPointer();
            struAddFaceDataCfg.dwJsonDataSize = strJsonData.length();

            ByteArrayInputStream picfile = new ByteArrayInputStream(faceBytes);
            int picdataLength = picfile.available();
            if (picdataLength > 200 * 1024) {
                throw new Exception("input file dataSize > 200kb");
            }

            HCNetSDK.BYTE_ARRAY ptrpicByte = new HCNetSDK.BYTE_ARRAY(picdataLength);
            picfile.read(ptrpicByte.byValue, 0, ptrpicByte.byValue.length);
            ptrpicByte.write();

            struAddFaceDataCfg.dwPicDataSize = picdataLength;
            struAddFaceDataCfg.lpPicData = ptrpicByte.getPointer();
            struAddFaceDataCfg.write();

            HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);
            IntByReference pInt = new IntByReference(0);

            int dwState = hcNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, struAddFaceDataCfg.getPointer(), struAddFaceDataCfg.dwSize, ptrOutuff.getPointer(), ptrOutuff.size(), pInt);
            //读取返回的json并解析
            ptrOutuff.read();
            String strResult = new String(ptrOutuff.byValue).trim();
//            log.info("dwState:" + dwState + ",strResult:" + strResult);

            if (strResult.isEmpty()) {
                return;
            }
            JSONObject jsonResult = new JSONObject(strResult);
            int statusCode = jsonResult.getInt("statusCode");
            //String statusString = jsonResult.getString("statusString");

            if (dwState == -1) {
                throw new Exception("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                log.error("下发人脸失败, json return:" + jsonResult.toString());
                //可以继续下发下一个
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                log.warn("下发人脸异常, json return:" + jsonResult.toString());
                return;
                //异常是长连接异常,不能继续下发后面的数据,需要重新建立长连接
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
                //返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如人脸图片不符合设备规范等原因,所以需要解析Json报文
                if (statusCode != 1) {
                    log.warn("下发人脸成功,但是有异常情况:" + jsonResult.toString());
                } else {
                    log.info("下发人脸成功,  json return:" + jsonResult.toString());
                }
                //可以继续下发下一个
            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                //下发人脸时:dwState其实不会走到这里,因为设备不知道我们会下发多少个人,所以长连接需要我们主动关闭
                log.info("下发人脸完成");
            } else {
                log.warn("下发人脸识别,其他状态:" + dwState);
            }

            if (!hcNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                log.error("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            }
        }
    }


    /**
     * 删除人脸数据
     * @param employeeNo 工号
     */
    public void delFaceInfo(String employeeNo) throws Exception {
        String strURL = "PUT /ISAPI/Intelligent/FDLib/FDSearch/Delete?format=json&FDID=1&faceLibType=blackFD";
        HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(BYTE_ARRAY_LEN);
        System.arraycopy(strURL.getBytes(), 0, ptrUrl.byValue, 0, strURL.length());
        ptrUrl.write();

        //输入删除条件
        HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(ISAPI_DATA_LEN);
        ptrInBuffer.read();
        String strInbuffer = "{\"FPID\":[{\"value\":\"" + employeeNo + "\"}]}";
        ptrInBuffer.byValue = strInbuffer.getBytes();
        ptrInBuffer.write();

        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        struXMLInput.dwSize = struXMLInput.size();
        struXMLInput.lpRequestUrl = ptrUrl.getPointer();
        struXMLInput.dwRequestUrlLen = ptrUrl.byValue.length;
        struXMLInput.lpInBuffer = ptrInBuffer.getPointer();
        struXMLInput.dwInBufferSize = ptrInBuffer.byValue.length;
        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(this.userId, struXMLInput, struXMLOutput)) {
            int iErr = hcNetSDK.NET_DVR_GetLastError();
            throw new Exception("NET_DVR_STDXMLConfig失败,错误号:" + iErr);
        } else {
            struXMLOutput.read();
            ptrOutByte.read();
            ptrStatusByte.read();
            String strOutXML = new String(ptrOutByte.byValue).trim();
            log.warn("删除人脸输出结果:" + strOutXML);
            String strStatus = new String(ptrStatusByte.byValue).trim();
            log.warn("删除人脸返回状态:" + strStatus);
        }
    }


    /**
     * @param control 0-关门,1-开门,2-常开,3-常关,4-恢复(恢复为普通状态)
     */
    public void controlGate(int control) throws Exception {
        int iErr = 0;
        //lGatewayIndex门编号(-1 表示对所有门进行操作;明眸仅支持一个门,故门编号填 1 即可)
//       dwStatic 0-关门,1-开门,2-常开,3-常关,4-恢复(恢复为普通状态)
        boolean lRemoteCtrl = hcNetSDK.NET_DVR_ControlGateway(this.userId, 1, control);
        if (!lRemoteCtrl) {
            iErr = hcNetSDK.NET_DVR_GetLastError();
            throw new Exception("远程控门失败,错误号:" + iErr);
        }
//        else {
//            System.out.println("NET_DVR_ControlGateway成功!");
//        }
    }
}

使用举例

HCNetDeviceUtil hcNetDeviceUtil = new HCNetDeviceUtil();
String ip = "192.168.1.10";
int port = 8000;
String username = "admin";
Sting password = "111";
Date start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-06-01 00:00:00");
Date end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-07-01 00:00:00");
try {
    hcNetDeviceUtil.loginDevice(ip, port, username, password);
    JSONArray events = hcNetDeviceUtil.getDeviceEvents(start, end);
    JSONArray users = hcNetDeviceUtil.searchUserInfo(0, 10);//查询用户信息前10条
    hcNetDeviceUtil.logout();
} catch (Exception e) {
    e.printStackTrace();
}

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论