海康威视门禁类设备(考勤打卡机类)数据对接

海康考勤机数据对接,有两种方式,一是让考勤机自己推送给我们,二是我们自己调用它的sdk获取数据,我都亲测可行了。
第一种比较简单,海康的机器本身有后台管理系统,并且支持配置数据http推送,我们只需要定义一个controller方法,把我们定义的方法的地址配进去就行了,大致如下:

但是靠机器推送我们就比较被动,也不够灵活,第二种方法:
一、准备工作:(我是eclipse开发的boot项目)
1、去海康官网或找技术支持要一份开发文档,如下图:

根据文档一步一步的开发就行了,以下是我踩过坑之后的开发步骤
2、把1中的部分文件添加到项目中,结构如下:

3、yml中配置:

注意,dllPath就是2步骤中hikvision文件夹的地址,需要根据部署环境的不同而改变
4、找厂家要机器的相关信息,也就是ip端口登录人啥的:

二、获取数据,代码如下:

传参:机器信息、查询开始时间、结束时间,调用XXXService中的getUserSignRecord方法就可以获取数据了:

XXXService代码如下:

@Service
public class XXXService {

    static HCNetSDK hCNetSDK = null;
    static int lUserID = -1;// 用户句柄
    static int iCharEncodeType = 0;// 设备字符集

    private @Autowired HikvisionProperties hikvisionProperties;// 3步骤中yml中配置信息的映射类

    private @Autowired EventSearch eventSearch;// 数据查询类

    /**
     * 获取机器数据
     */
    public List<EventLog> getUserSignRecord(OfficeTecoMachine teco, Date stratDate, Date endDate) throws Exception {
        // 登录设备
        this.init(teco);
        // 查询数据
        List<EventLog> eventLogList = this.eventSearch.searchAllEvent(lUserID, teco.getTecoNumber(), stratDate, endDate);
        // 注销设备
        this.logout();
        return eventLogList;
    }

    /**
     * 初始化SDK并登录设备
     */
    public void init(OfficeTecoMachine teco) throws InterruptedException {
        if (hCNetSDK == null && !createSDKInstance()) {
            HikvisionLogUtils.HIKVISION_LOG.error("加载sdk失败,请检查海康dll文件的路径是否配置正确");
            return;
        }
        //SDK初始化,和进程保持同步,仅需要调用一次
        hCNetSDK.NET_DVR_Init();
        //开启SDK日志打印
        hCNetSDK.NET_DVR_SetLogToFile(hikvisionProperties.getSdkLogLev(), hikvisionProperties.getSdkLogPath(), false);
        //设备登录
        lUserID=loginDevice(teco.getHost(),
                (short)teco.getPort(),
                teco.getLoginUser(),
                teco.getLoginPassWord());
        // 增加sleep时间,保证程序一直运行
        Thread.sleep(1000);

    }
    
    /**
     * 初始化SDK
     */
    private boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                try {
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(hikvisionProperties.getDllPath() + File.separator + "HCNetSDK.dll", HCNetSDK.class);
                } catch (Throwable t) {
                    HikvisionLogUtils.HIKVISION_LOG.error("海康考勤机loadLibrary:{},出错", hikvisionProperties.getDllPath(), t);
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 登录设备,支持 V40 和 V30 版本,功能一致。
     *
     * @param ip      设备IP地址
     * @param port    SDK端口,默认为设备的8000端口
     * @param user    设备用户名
     * @param psw     设备密码
     * @return 登录成功返回用户ID,失败返回-1
     */
    public static int loginDevice(String ip, short port, String user, String psw) {
        // 创建设备登录信息和设备信息对象
        HCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        HCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();

        // 设置设备IP地址
        byte[] deviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        byte[] ipBytes = ip.getBytes();
        System.arraycopy(ipBytes, 0, deviceAddress, 0, Math.min(ipBytes.length, deviceAddress.length));
        loginInfo.sDeviceAddress = deviceAddress;

        // 设置用户名和密码
        byte[] userName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        byte[] password = psw.getBytes();
        System.arraycopy(user.getBytes(), 0, userName, 0, Math.min(user.length(), userName.length));
        System.arraycopy(password, 0, loginInfo.sPassword, 0, Math.min(password.length, loginInfo.sPassword.length));
        loginInfo.sUserName = userName;

        // 设置端口和登录模式
        loginInfo.wPort = port;
        loginInfo.bUseAsynLogin = false; // 同步登录
        loginInfo.byLoginMode = 0; // 使用SDK私有协议

        // 执行登录操作
        int userID = hCNetSDK.NET_DVR_Login_V40(loginInfo, deviceInfo);
        if (userID == -1) {
            HikvisionLogUtils.HIKVISION_LOG.error("登录失败,错误码为: " + hCNetSDK.NET_DVR_GetLastError());
        } else {
            HikvisionLogUtils.HIKVISION_LOG.info(ip + " 设备登录成功!");
        }
        // 返回登录结果
        return userID;
    }

    /**
     * 登出操作
     */
    public void logout(){
        /**登出和清理,释放SDK资源*/
        if (lUserID>=0) {
            if (!hCNetSDK.NET_DVR_Logout(lUserID)) {
                HikvisionLogUtils.HIKVISION_LOG.error("设备注销失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
                return;
            }
            HikvisionLogUtils.HIKVISION_LOG.info("设备注销成功!!!");
        }
    }
}
EventSearch 类代码如下:

@Service
public class EventSearch {

    /**
     * 门禁事件查询,基于起止时间,事件类型进行查询
     * @param lUserID
     * @param tecoNumber
     * @param stratDate
     * @param endDate
     * @return
     * @throws UnsupportedEncodingException
     * @throws InterruptedException
     */
    public List<EventLog> searchAllEvent(int lUserID, String tecoNumber, Date stratDate, Date endDate) throws UnsupportedEncodingException, InterruptedException {
        EventLog eventLog = null;
        HCNetSDK.NET_DVR_ACS_EVENT_COND struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();
        struAcsEventCond.read();
        struAcsEventCond.dwSize = struAcsEventCond.size();
        HikvisionLogUtils.HIKVISION_LOG.error(tecoNumber+"主机数据:"+struAcsEventCond.dwSize);
        //查询全部主次类型的报警
        struAcsEventCond.dwMajor = 0; // 主次事件类型设为0,代表查询所有事件
        struAcsEventCond.dwMinor = 0; //
        //开始时间
        struAcsEventCond.struStartTime.dwYear = JodaTimeUtils.getYear(stratDate);
        struAcsEventCond.struStartTime.dwMonth = JodaTimeUtils.getMonth(stratDate);
        struAcsEventCond.struStartTime.dwDay = JodaTimeUtils.getDayOfMonth(stratDate);
        struAcsEventCond.struStartTime.dwHour = 0;
        struAcsEventCond.struStartTime.dwMinute = 0;
        struAcsEventCond.struStartTime.dwSecond = 0;
        //结束时间
        struAcsEventCond.struEndTime.dwYear = JodaTimeUtils.getYear(endDate);
        struAcsEventCond.struEndTime.dwMonth = JodaTimeUtils.getMonth(endDate);
        struAcsEventCond.struEndTime.dwDay = JodaTimeUtils.getDayOfMonth(endDate);
        struAcsEventCond.struEndTime.dwHour = 23;
        struAcsEventCond.struEndTime.dwMinute = 59;
        struAcsEventCond.struEndTime.dwSecond = 59;
        struAcsEventCond.wInductiveEventType = 1;
        struAcsEventCond.byPicEnable = 0; //是否带图片,0-不带图片,1-带图片
        struAcsEventCond.write();
        Pointer ptrStruEventCond = struAcsEventCond.getPointer();
        int m_lSearchEventHandle = XXXService.hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_ACS_EVENT, ptrStruEventCond, struAcsEventCond.size(), null, null);
        if (m_lSearchEventHandle<=-1) {
            HikvisionLogUtils.HIKVISION_LOG.error("NET_DVR_StartRemoteConfig调用失败,错误码:" + XXXService.hCNetSDK.NET_DVR_GetLastError());
        }
        HCNetSDK.NET_DVR_ACS_EVENT_CFG struAcsEventCfg = new HCNetSDK.NET_DVR_ACS_EVENT_CFG();
        struAcsEventCfg.read();
        struAcsEventCfg.dwSize = struAcsEventCfg.size();
        struAcsEventCfg.write();
        Pointer ptrStruEventCfg = struAcsEventCfg.getPointer();
        List<EventLog> eventLogList = new ArrayList<EventLog>();
        HikvisionLogUtils.HIKVISION_LOG.info("=========dwSize="+struAcsEventCond.dwSize);
        while (true) {
            int dwEventSearch = XXXService.hCNetSDK.NET_DVR_GetNextRemoteConfig(m_lSearchEventHandle, ptrStruEventCfg, struAcsEventCfg.size());
            if (dwEventSearch <= -1) {
                HikvisionLogUtils.HIKVISION_LOG.error("NET_DVR_GetNextRemoteConfig接口调用失败,错误码:" + XXXService.hCNetSDK.NET_DVR_GetLastError());
                break;
            }
            if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {
                HikvisionLogUtils.HIKVISION_LOG.info("配置等待....");
                Thread.sleep(10);
                continue;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) {
                HikvisionLogUtils.HIKVISION_LOG.info("获取事件完成");
                break;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {
                HikvisionLogUtils.HIKVISION_LOG.info("获取事件出现异常");
                break;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {
                struAcsEventCfg.read();
                // 只获取考勤签到事件
                if(struAcsEventCfg.dwMajor != 5 || struAcsEventCfg.dwMinor != 75){
                    continue;
                }
                eventLog = new EventLog();
                eventLog.setAccessControllerEvent(new AccessControllerEvent());
                eventLog.setDateTime(struAcsEventCfg.struTime.dwYear+"-"+struAcsEventCfg.struTime.dwMonth+"-"+struAcsEventCfg.struTime.dwDay+
                        " "+struAcsEventCfg.struTime.dwHour+":"+struAcsEventCfg.struTime.dwMinute+":"+struAcsEventCfg.struTime.dwSecond);
                eventLog.getAccessControllerEvent().setEmployeeNoString(new String(struAcsEventCfg.struAcsEventInfo.byEmployeeNo).trim());
                eventLog.getAccessControllerEvent().setAttendanceStatus(String.valueOf(struAcsEventCfg.struAcsEventInfo.byAttendanceStatus));
                eventLog.getAccessControllerEvent().setCurrentProcessVerifyMode(String.valueOf(struAcsEventCfg.struAcsEventInfo.byCurrentVerifyMode));
                eventLog.getAccessControllerEvent().setDeviceName(tecoNumber);
                eventLogList.add(eventLog);
                continue;
            }
        }
        if (!XXXService.hCNetSDK.NET_DVR_StopRemoteConfig(m_lSearchEventHandle)) {
            HikvisionLogUtils.HIKVISION_LOG.error("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + XXXService.hCNetSDK.NET_DVR_GetLastError());
        } else {
            HikvisionLogUtils.HIKVISION_LOG.info("NET_DVR_StopRemoteConfig接口成功");
        }
        return eventLogList;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值