天天看点

中控考勤机Java二次开发(附Demo)

前言:前几天项目改造,需要将中控702设备集成到网站后台上去;找官方在线客服、电话客服、售后技术QQ都表示只提供C#语言的Demo,无奈只能去找度娘各种解决方案,网上相关教程较多 也挺杂的,最后终于好了!

借鉴:

https://blog.csdn.net/qq_24511731/article/details/55049918?locationNum=9&fps=1

前期准备:先尝试中控考勤软件是否能正常连接:如果Zk Time都没有搞定,先去联系中控官网客服解决。

  1. jacob-1.18版本
  2. jdk1.732位
  3. 将jacob.jar 放入项目 WEB-INFO/lib下导入
  4. 将jacob-1.18-x64.dll 放入32位 jdk/bin目录下,我的是:C:\Program Files (x86)\Java\jdk1.7.0_79\bin;
  5. 将中控考勤机sdk 的dll文件全部放入 c:\windows\syswow64 目录下(我的是64位系统,32位的话没测试,放入system32目录下);
  6. 运行cmd 注册zkemkeeper.dll —>regsvr32 c:\windows\syswow64\zkemkeeper.dll

    下载DEMO包:中控JavaDemo资源

    详细:

    中控考勤机Java二次开发(附Demo)

    附四个类:

    1:ZkemUtils工具类:主要是一些常用的方法,

    如:

1: 获取所有用户信息----getUserInfo

2: 根据单个用户ID获取用户信息----getUserInfoByNumber

3: 创建、修改用户信息----setUserInfo

4: 获取当天打卡信息----getUserOneDayInfo(Object userNumber )传入“用户ID”只返回当天当前用户的打卡信息,传“null”返当天所有的打卡信息

5:删除用户信息----delectUserById(String dwEnrollNumber)传入需要删除的用户ID。

使用前先在构造快中配置考勤机的IP和端口

中控考勤机Java二次开发(附Demo)

ZkemUtils工具类:

package com.zt;



import cn.hutool.core.date.DateUtil;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.STA;
import com.jacob.com.Variant;
import com.zt.po.LogData;
import com.zt.po.UserInfo;

import java.util.*;

public class ZkemSDKUtils {
    public static void main(String[] args) {
        ZkemSDKUtils sk = new ZkemSDKUtils();
        boolean flag = readGeneralLogData();
       List<LogData> userOneDayInfo = getUserOneDayInfo(null);
        System.out.println(userOneDayInfo.toString());
        boolean auth = ZkemSDKUtils.setUserInfo("6", "唐涛", null, 0, true);
        System.out.println(auth);
        List<UserInfo> userInfo = ZkemSDKUtils.getUserInfo();
        System.out.println(userInfo.toString());
        regEvent();
    }

    {
        boolean connect = connect("192.168.1.18", 4370);
    }
    //zkemkeeper.ZKEM.1 为zkemkeeper.dll 注册成功后 在注册表可以查看:HKEY_CLASSES_ROOT最下面
    private static ActiveXComponent zkem = new ActiveXComponent("zkemkeeper.ZKEM.1");

    /**
     * 连接考勤机
     *
     * @param address 考勤机地址
     * @param port    端口号
     * @return
     */
    public static boolean connect(String address, int port) {
        boolean result = zkem.invoke("Connect_NET", address, port).getBoolean();
        return result;
    }

    /**
     * 启动事件监听
     */
    public static void  regEvent(){
        zkem.invoke("RegEvent", new Variant(1), new Variant(1));
        zkem.invoke("ReadRTLog", new Variant(1));
        zkem.invoke("GetRTLog", new Variant(1));

        new DispatchEvents(zkem.getObject(), new SensorEvents());
        new STA().doMessagePump();
    }
    /**
     * 读取考勤记录到pc缓存。配合getGeneralLogData使用
     *
     * @return
     */
    public static boolean readGeneralLogData() {
        boolean result = zkem.invoke("ReadGeneralLogData", 4).getBoolean();
        return result;
    }

    /**
     * 读取该时间之后的最新考勤数据。 配合getGeneralLogData使用。//网上说有这个方法,但是我用的开发文档没有这个方法,也调用不到,我在controller中处理获取当天数据
     *
     * @param lastest
     * @return
     */
    public static boolean readLastestLogData(Date lastest) {
        boolean result = zkem.invoke("ReadLastestLogData", 2018 - 07 - 24).getBoolean();
        return result;
    }

    /**
     * 获取缓存中的考勤数据。配合readGeneralLogData / readLastestLogData使用。
     *
     * @return 返回的map中,包含以下键值:
     * "EnrollNumber"   人员编号
     * "Time"           考勤时间串,格式: yyyy-MM-dd HH:mm:ss
     * "VerifyMode"     验证方式  1:指纹 2:面部识别
     * "InOutMode"      考勤状态 0:上班 1:下班 2:外出 3:外出返回 4:加班签到 5:加班签退
     * "Year"          考勤时间:年
     * "Month"         考勤时间:月
     * "Day"           考勤时间:日
     * "Hour"            考勤时间:时
     * "Minute"        考勤时间:分
     * "Second"        考勤时间:秒
     */
    public static List<Map<String, Object>> getGeneralLogData() {
        Variant dwMachineNumber = new Variant(1, true);//机器号

        Variant dwEnrollNumber = new Variant("", true);
        Variant dwVerifyMode = new Variant(0, true);
        Variant dwInOutMode = new Variant(0, true);
        Variant dwYear = new Variant(0, true);
        Variant dwMonth = new Variant(0, true);
        Variant dwDay = new Variant(0, true);
        Variant dwHour = new Variant(0, true);
        Variant dwMinute = new Variant(0, true);
        Variant dwSecond = new Variant(0, true);
        Variant dwWorkCode = new Variant(0, true);
        List<Map<String, Object>> strList = new ArrayList<Map<String, Object>>();
        boolean newresult = false;
        do {
            Variant vResult = Dispatch.call(zkem, "SSR_GetGeneralLogData", dwMachineNumber, dwEnrollNumber, dwVerifyMode, dwInOutMode, dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond, dwWorkCode);
            newresult = vResult.getBoolean();
            if (newresult) {
                String enrollNumber = dwEnrollNumber.getStringRef();

                //如果没有编号,则跳过。
                if (enrollNumber == null || enrollNumber.trim().length() == 0)
                    continue;
                String month = dwMonth.getIntRef() + "";
                String day = dwDay.getIntRef() + "";
                if (dwMonth.getIntRef() < 10) {
                    month = "0" + dwMonth.getIntRef();
                }
                if (dwDay.getIntRef() < 10) {
                    day = "0" + dwDay.getIntRef();
                }
                String validDate = dwYear.getIntRef() + "-" + month + "-" + day;
                //String currentDate = DateUtils.getCurrentTime("yyyy-MM-dd");
                String currentDate = DateUtil.today();
                if (currentDate.equals(validDate)) {
                    Map<String, Object> m = new HashMap<String, Object>();
                    //Map<String, Object> user = getUserInfoByNumber(enrollNumber);
                    m.put("EnrollNumber", enrollNumber);
                    m.put("Time", dwYear.getIntRef() + "-" + dwMonth.getIntRef() + "-" + dwDay.getIntRef() + " " + dwHour.getIntRef() + ":" + dwMinute.getIntRef() + ":" + dwSecond.getIntRef());
                    m.put("VerifyMode", dwVerifyMode.getIntRef());
                    m.put("InOutMode", dwInOutMode.getIntRef());
                    m.put("Year", dwYear.getIntRef());
                    m.put("Month", dwMonth.getIntRef());
                    m.put("Day", dwDay.getIntRef());
                    m.put("Hour", dwHour.getIntRef());
                    m.put("Minute", dwMinute.getIntRef());
                    m.put("Second", dwSecond.getIntRef());
                    strList.add(m);
                }
            }
        } while (newresult == true);
        return strList;
    }

    /**
     * 获取用户信息
     *
     * @return 返回的Map中,包含以下键值:
     * "EnrollNumber"  人员编号
     * "Name"          人员姓名
     * "Password"      人员密码
     * "Privilege"     特权 0位普通 3特权
     * "Enabled"       是否启用
     */
    public static List<UserInfo> getUserInfo() {
        List<UserInfo> userInfoList = new LinkedList<>();
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        //将用户数据读入缓存中。
        boolean result = zkem.invoke("ReadAllUserID", 1).getBoolean();

        Variant v0 = new Variant(1);
        Variant sdwEnrollNumber = new Variant("", true);
        Variant sName = new Variant("", true);
        Variant sPassword = new Variant("", true);
        Variant iPrivilege = new Variant(0, true);
        Variant bEnabled = new Variant(false, true);

        while (result) {
            //从缓存中读取一条条的用户数据
            result = zkem.invoke("SSR_GetAllUserInfo", v0, sdwEnrollNumber, sName, sPassword, iPrivilege, bEnabled).getBoolean();

            //如果没有编号,跳过。
            String enrollNumber = sdwEnrollNumber.getStringRef();
            if (enrollNumber == null || enrollNumber.trim().length() == 0)
                continue;

            //由于名字后面会产生乱码,所以这里采用了截取字符串的办法把后面的乱码去掉了,以后有待考察更好的办法。
            //只支持2位、3位、4位长度的中文名字。
            String name = sName.getStringRef();
            int index = name.indexOf("\0");
            String newStr = "";
            if (index>-1){
                name = name.substring(0,index);
            }
            if (sName.getStringRef().length() > 4) {
                name = sName.getStringRef().substring(0, 4);
            }
            //如果没有名字,跳过。
            if (name.trim().length() == 0)
                continue;
            UserInfo userInfo = new UserInfo();
            userInfo.setEnrollNumber(enrollNumber);
            userInfo.setName(name);
            userInfo.setPassword(sPassword.getStringRef());
            userInfo.setPrivilege(iPrivilege.getIntRef());
            userInfo.setEnabled((Boolean)bEnabled.getBooleanRef());
            userInfoList.add(userInfo);
        }
        return userInfoList;
    }


    /**
     * 设置用户信息
     *
     * @param number
     * @param name
     * @param password
     * @param isPrivilege 0為普通用戶,3為管理員;
     * @param enabled 是否啟用
     * @return
     */
    public static boolean setUserInfo(String number, String name, String password, int isPrivilege, boolean enabled) {
        Variant v0 = new Variant(1);
        Variant sdwEnrollNumber = new Variant(number, true);
        Variant sName = new Variant(name, true);
        Variant sPassword = new Variant(password, true);
        Variant iPrivilege = new Variant(isPrivilege, true);
        Variant bEnabled = new Variant(enabled, true);

        boolean result = zkem.invoke("SSR_SetUserInfo", v0, sdwEnrollNumber, sName, sPassword, iPrivilege, bEnabled).getBoolean();
        return result;
    }

    /**
     * 获取用户信息
     *
     * @param number 考勤号码
     * @return
     */
    public static Map<String, Object> getUserInfoByNumber(String number) {
        Variant v0 = new Variant(1);
        Variant sdwEnrollNumber = new Variant(number, true);
        Variant sName = new Variant("", true);
        Variant sPassword = new Variant("", true);
        Variant iPrivilege = new Variant(0, true);
        Variant bEnabled = new Variant(false, true);
        boolean result = zkem.invoke("SSR_GetUserInfo", v0, sdwEnrollNumber, sName, sPassword, iPrivilege, bEnabled).getBoolean();
        if (result) {
            Map<String, Object> m = new HashMap<String, Object>();
            m.put("EnrollNumber", number);
            m.put("Name", sName.getStringRef());
            m.put("Password", sPassword.getStringRef());
            m.put("Privilege", iPrivilege.getIntRef());
            m.put("Enabled", bEnabled.getBooleanRef());
            return m;
        }
        return null;
    }



    /**
     * 查詢所有/指定ID的打卡信息;
     * @param userNumber
     * @return
     */
    public static List<LogData> getUserOneDayInfo(Object userNumber){
        ZkemSDKUtils sdk = new ZkemSDKUtils();
        Map<String,Object> userInfo = new HashMap<String,Object>();
        List<LogData> logDateList = new ArrayList<>();
        //连接考勤机;
        boolean connect = connect("192.168.1.18", 4370);
        if(connect){
            List<Map<String, Object>> generalLogDataAll = ZkemSDKUtils.getGeneralLogData();
            for (int i = 0; i < generalLogDataAll.size(); i++) {
                //System.out.println(generalLogDataAll.get(i));
                String Year =String.valueOf(generalLogDataAll.get(i).get("Year"));
                String Hour = String.valueOf(generalLogDataAll.get(i).get("Hour"));
                String InOutMode = String.valueOf(generalLogDataAll.get(i).get("InOutMode"));
                String Time = String.valueOf(generalLogDataAll.get(i).get("Time"));
                String Second = String.valueOf(generalLogDataAll.get(i).get("Second"));
                String Minute = String.valueOf(generalLogDataAll.get(i).get("Minute"));
                String EnrollNumber = String.valueOf(generalLogDataAll.get(i).get("EnrollNumber"));
                String Day = String.valueOf(generalLogDataAll.get(i).get("Day"));
                String Month = String.valueOf(generalLogDataAll.get(i).get("Month"));
                String VerifyMode = String.valueOf(generalLogDataAll.get(i).get("VerifyMode"));
                LogData logData = new LogData();
                logData.setYear(Year);
                logData.setHour(Hour);
                logData.setInOutMode1(InOutMode);
                logData.setTime(Time);
                logData.setSecond(Second);
                logData.setMinute(Minute);
                logData.setEnrollNumber(EnrollNumber);
                logData.setDay(Day);
                logData.setMonth(Month);
                logData.setVerifyMode(VerifyMode);

                if (EnrollNumber.equals(userNumber)&&userNumber!=null){
                    logDateList.add(logData);
                }else if (userNumber==null){
                    logDateList.add(logData);
                }
            }
            return logDateList;

        }
        return null;
    }
    /**
     * 删除用户;
     */
    public static Boolean delectUserById(String dwEnrollNumber){
        Variant v0 = new Variant(1);
        Variant sdwEnrollNumber = new Variant(dwEnrollNumber, true);
        /**
         * sdwBackupNumber:
         * 一般范围为 0-9,同时会查询该用户是否还有其他指纹和密码,如都没有,则删除该用户
         * 当为 10 是代表删除的是密码,同时会查询该用户是否有指纹数据,如没有,则删除该用户
         * 11 和 13 是代表删除该用户所有指纹数据,
         * 12 代表删除该用户(包括所有指纹和卡号、密码数据)
         */
        Variant sdwBackupNumber = new Variant(12);
        /**
         * 删除登记数据,和 SSR_DeleteEnrollData 不同的是删除所有指纹数据可用参数 13 实现,该函数具有更高效率
         */
        return zkem.invoke("SSR_DeleteEnrollDataExt", v0, sdwEnrollNumber, sdwBackupNumber).getBoolean();
    }
}

           

2:SensorEvents 负责事件监听OnAttTransactionEx重要

package com.zt;

import com.jacob.com.Variant;

public class SensorEvents {

	public void OnConnected(Variant[] arge){
		System.out.println("当成功连接机器时触发该事件,无返回值====");
	}

	public void OnDisConnected(Variant[] arge){
		System.out.println("当断开机器时触发该事件,无返回值====");
	}

	public void OnAlarm(Variant[] arge){
		System.out.println("当机器报警时触发该事件===="+arge);
	}

	public void OnAttTransactionEx(Variant[] arge){
		System.out.println("id:"+arge[0]);
		System.out.println("是否有效:0有效 1无效"+arge[1]);
		System.out.println("考勤状态:0 上班 1下班 2外出 3外出返回 4 加班签到 5 加班签退...."+arge[2]);
		System.out.println("验证方式 0:密码  1;指纹 15:刷脸认证"+arge[3]);
		System.out.println("验证时间"+arge[4]+"-"+arge[5]+"-"+arge[6]+"-"+arge[7]+":"+arge[8]+":"+arge[9]+" "+arge[10]);
		/*for (int i = 0; i < arge.length; i++) {
			System.out.println(arge[i]);

		}*/
		//System.out.println(arge.toString());
		System.out.println("当验证通过时触发该事件====**"+arge);
	}

	public void OnEnrollFingerEx(Variant[] arge){
		System.out.println("登记指纹时触发该事件===="+arge.clone());
	}

	public void OnFinger(Variant[] arge){
		System.out.println("当机器上指纹头上检测到有指纹时触发该消息,无返回值");
	}

	public void OnFingerFeature(Variant[] arge){
		System.out.println("登记用户指纹时,当有指纹按下时触发该消息===="+arge);
	}

	public void OnHIDNum(Variant[] arge){
		System.out.println("当刷卡时触发该消息===="+arge);
	}

	public void OnNewUser(Variant[] arge){
		System.out.println("当成功登记新用户时触发该消息===="+arge);
	}

	public void OnVerify(Variant[] arge){
		System.out.println("当用户验证时触发该消息===="+arge);
	}

	public void OnWriteCard(Variant[] arge){
		System.out.println("当机器进行写卡操作时触发该事件===="+arge);
	}

	public void OnEmptyCard(Variant[] arge){
		System.out.println("当清空 MIFARE 卡操作时触发该事件===="+arge);
	}

	public void OnEMData(Variant[] arge){
		System.out.println("当机器向 SDK 发送未知事件时,触发该事件===="+arge);
	}

} 
           

下面是两个封装的Bean对象;

3:LogData(接收OnAttTransactionEx方法返回的args数组)

package com.zt.po;

/**
 * 获取缓存中的考勤数据。配合readGeneralLogData / readLastestLogData使用。
 *      *
 *      * @return 返回的map中,包含以下键值:
 *      * "EnrollNumber"   人员编号
 *      * "Time"           考勤时间串,格式: yyyy-MM-dd HH:mm:ss
 *      * "VerifyMode"     验证方式  1:指纹 2:面部识别
 *      * "InOutMode"      考勤状态 0:上班 1:下班 2:外出 3:外出返回 4:加班签到 5:加班签退
 *      * "Year"          考勤时间:年
 *      * "Month"         考勤时间:月
 *      * "Day"           考勤时间:日
 *      * "Hour"            考勤时间:时
 *      * "Minute"        考勤时间:分
 *      * "Second"        考勤时间:秒
 *
 */
public class LogData {
    private String Year;
    private String Hour;
    private String InOutMode;
    private String Time;
    private String InOutMode1;
    private String Second;
    private String Minute;
    private String EnrollNumber;
    private String Day;
    private String Month;
    private String VerifyMode;

    public LogData(String year, String hour, String inOutMode, String time, String inOutMode1, String second, String minute, String enrollNumber, String day, String month, String verifyMode) {
        Year = year;
        Hour = hour;
        InOutMode = inOutMode;
        Time = time;
        InOutMode1 = inOutMode1;
        Second = second;
        Minute = minute;
        EnrollNumber = enrollNumber;
        Day = day;
        Month = month;
        VerifyMode = verifyMode;
    }

    public String getYear() {
        return Year;
    }

    public void setYear(String year) {
        Year = year;
    }

    public String getHour() {
        return Hour;
    }

    public void setHour(String hour) {
        Hour = hour;
    }

    public String getInOutMode() {
        return InOutMode;
    }

    public void setInOutMode(String inOutMode) {
        InOutMode = inOutMode;
    }

    public String getTime() {
        return Time;
    }

    public void setTime(String time) {
        Time = time;
    }

    public String getInOutMode1() {
        return InOutMode1;
    }

    public void setInOutMode1(String inOutMode1) {
        InOutMode1 = inOutMode1;
    }

    public String getSecond() {
        return Second;
    }

    public void setSecond(String second) {
        Second = second;
    }

    public String getMinute() {
        return Minute;
    }

    public void setMinute(String minute) {
        Minute = minute;
    }

    public String getEnrollNumber() {
        return EnrollNumber;
    }

    public void setEnrollNumber(String enrollNumber) {
        EnrollNumber = enrollNumber;
    }

    public String getDay() {
        return Day;
    }

    public void setDay(String day) {
        Day = day;
    }

    public String getMonth() {
        return Month;
    }

    public void setMonth(String month) {
        Month = month;
    }

    public String getVerifyMode() {
        return VerifyMode;
    }

    public void setVerifyMode(String verifyMode) {
        VerifyMode = verifyMode;
    }

    public LogData(){};
}

           

4:封装的用户信息Bean;

package com.zt.po;

public class UserInfo {
    private String name;
    private Boolean Enabled;
    private String Password;
    private Integer Privilege;
    private String EnrollNumber;

    public UserInfo(String name, Boolean enabled, String password, Integer privilege, String enrollNumber) {
        this.name = name;
        Enabled = enabled;
        Password = password;
        Privilege = privilege;
        EnrollNumber = enrollNumber;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean getEnabled() {
        return Enabled;
    }

    public void setEnabled(Boolean enabled) {
        Enabled = enabled;
    }

    public String getPassword() {
        return Password;
    }

    public void setPassword(String password) {
        Password = password;
    }

    public Integer getPrivilege() {
        return Privilege;
    }

    public void setPrivilege(Integer privilege) {
        Privilege = privilege;
    }

    public String getEnrollNumber() {
        return EnrollNumber;
    }

    public void setEnrollNumber(String enrollNumber) {
        EnrollNumber = enrollNumber;
    }

    public UserInfo(){};
}

           

萌新第一次发帖,希望能帮到大家,使用我的这个Demo有疑问欢迎私我或者QQ:502555270联系哈。

继续阅读