记录java(jdk 1.8 64位)连接中控考勤机的坑

项目背景: 公司项目因为需要对接硬件(中控考勤机)获取人员考勤数据,而公司又不具备C的开发能力,所以想通过java直接操作打卡机信息,前前后后总共经过了十来天的开发时间,躺过不少的坑,耽误了些时间,特此记录,本文记录了两种获取考勤数据的方法,前一种需要经过第三方的软件(收费的,最后废弃),第二种则是直接java连接打卡机,两种方式都经过测试,都可以拿到想要的数据!

一. 借鉴第三方软件(公司购买设备时提供技术支持,安装他们的考勤系统,最终形成mdb文件,java直接读取mdb文件获取数据)
  1. 打卡机设备厂商提供的源码为C语言,数据库为Access数据库,而我的项目采用的是java + mysql 因为开发周期有限,所以最后采用的快捷方法就是java直接定时读取mdb文件获取数据再写入mysql中进行自己的业务逻辑处理,下面贴上读取的代码(工具类也是网上拿过来的)
public static List<Object> resoMdbUser(String mdbPath, String username, String password) throws Exception {
        List<Object> list = new ArrayList<>();
        Properties prop = new Properties();
        //设置编码
        prop.put("charSet", "UTF-8");
        prop.put("user", username);
        prop.put("password", password);
        //数据地址
        String dbUrl = "jdbc:ucanaccess://" + mdbPath;
        //引入驱动
        Class.forName("net.ucanaccess.jdbc.UcanaccessDriver").newInstance();
        Connection conn = null;
        ResultSet tables = null;
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try {
            //连接数据库资源
            conn = DriverManager.getConnection(dbUrl, prop);
            tables = conn.getMetaData().getTables(mdbPath, null, null, new String[]{"TABLE"});
            //遍历获取多张表数据
            while (tables.next()) {
                Map<String, Object> tableMap = new HashMap<>(16);
                Set<String> columnList = new HashSet<>();
                List<Map<String,String>> dataList = new ArrayList<>();
//                String tableName = tables.getString(3);
                String tableName = "USERINFO" ;
                preparedStatement = conn.prepareStatement("select * from " + tableName);
                rs = preparedStatement.executeQuery();
                ResultSetMetaData data = rs.getMetaData();
                while (rs.next()) {
                    Map<String, String> map = new HashMap<>();
                    for (int i = 1; i <= data.getColumnCount(); i++) {
                        //列名
                        String columnName = data.getColumnName(i);
                        map.put(columnName, rs.getString(i));
                        columnList.add(columnName);
                    }
                    dataList.add(map);
                }
                tableMap.put("data", dataList);
                list.add(tableMap);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeA1l(conn, preparedStatement, tables, rs);
        }
        return list;
    }

2.返回的数据格式为:

[{data=[{ZIP=null, ATT=1, VERIFICATIONMETHOD=null, SECURITYFLAGS=null, ValidCount=0, OPHONE=null, FaceGroup=0, Gender=null, IDCardName=null, Name=1, VerifyCode=0, FSelected=FALSE, USERID=1, InheritDeptSch=1, IDCardNation=null, PHOTO=null, OVERTIME=1, BIRTHDAY=null, UseAccGroupTZ=1, PAGER=null, EMPRIVILEGE=0, AutoSchPlan=1, InheritDeptRule=1, IDCard_MainCard=null, IDCardDN=null, IDCardNotice=null, IDCard_ViceCard=null, IDCardAddr=null, MINZU=null, IDCardNewAddr=null, FPHONE=null, RegisterOT=1, PASSWORD=null, IDCardReserve=null, Expires=0, IDCardValidTime=null, SEP=1, Badgenumber=1, TimeZone1=1, TimeZone2=0, TimeZone3=0, IDCardGender=null, IDCardBirth=null, STATE=null, IDCardISSUER=null, INLATE=1, privilege=0, IDCardNo=null, street=null, HOLIDAY=1, IDCardSN=null, MinAutoSchInterval=24, AccGroup=1, Notes=null, OUTEARLY=1, LUNCHDURATION=1, EMail=null, mverifypass=null, ValidTimeEnd=null, SSN=null, CardNo=null, InheritDeptSchClass=1, CITY=null, DEFAULTDEPTID=1, ValidTimeBegin=null, HIREDDAY=null, TITLE=null}]}]
  1. 中控考勤机对应的表结构信息网上教程都有,这里就不贴了,拿到数据解析成自己想要的即可,下面为解析demo;
List<Object> userObject = MdbUtils.resoMdbUser(mdbPath, "", "");
            //拿到第一个data
            Object userObj = userObject.get(0);
            //转成json数组
            String userJs = JSON.toJSONString(userObj);
            //转成json对象
            JSONObject userJsonObj = JSONObject.parseObject(userJs);
            //根据data去取值
            JSONArray usersData = userJsonObj.getJSONArray("data");
            //遍历数据
            for(int i = 0; i < usersData.size(); i++){
                JSONObject userJson = usersData.getJSONObject(i);
                //用户登记号
                String Badgenumber = userJson.getString("Badgenumber");
                //用户id
                Integer userId = userJson.getInteger("USERID");
                //姓名
                String name = userJson.getString("Name");
                //部门编号
                Integer defaultdeptId = userJson.getInteger("DEFAULTDEPTID");
                Integer att = userJson.getInteger("ATT");
                //下面进行业务处理即可
                /***
                *
                */
              }

至此第一种方法获取考勤数据结束,此方法有个弊端就是mdb文件需要用户手动打开第三方的考勤系统软件才能往mdb文件里写入,另外本人觉得定时去读取也挺鸡肋的,仅供参考;

二. 因为第一种方法是第三方软件是收费版本,后公司就想通过java直接连接打卡机,获取数据,就省去了一大笔第三方公司的费用(资本主义啊,是能省一点是一点),下面介绍java连接打卡机的步骤;
  1. 网上很多说 中控只支持32位的jdk,本人一开始也是这么认为的,但经过测试64位的也是可以的
    连接步骤:
    1. jacob-1.19版本;
    2. 在resources目录下新建lib文件夹, 将jacob.jar 放入项目ib导入;
    3. maven里导入本地jar包;
    4.将jacob-1.19-x64.dll 放入64位 jre/bin目录下;
    5.将中控考勤机sdk 的dll文件全部放入 c:\windows\system32 目录下;
    6.运行cmd 注册zkemkeeper.dll —>regsvr32 c:\windows\system32\zkemkeeper.dll (也可以使用 自动注册.bat)
    7.已经配置完毕,进行代码测试;
<!--中控SDK-->
        <dependency>
            <groupId>com.zkem</groupId>
            <artifactId>jacob</artifactId>
            <version>1.19</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/jacob.jar</systemPath>
        </dependency>

	<!--考勤机连接代码-->
    //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;
    }
    /**
     * 设置考勤机密码
     * @return
     */
    public static boolean password(int password) {
        boolean result = zkem.invoke("SetCommPassword", password).getBoolean();
        return result;
    }
    /**
     * 断开考勤机链接
     */
    public static void disConnect() {
        zkem.invoke("Disconnect");
    }
boolean password = ZkemSDKUtils.password(123456);
        boolean connect = ZkemSDKUtils.connect("192.168.0.888", 4370);
        System.out.println("connect:"+connect);
        System.out.println("password:"+password);
注意:一般设备都设置了密码,所以需要先设置密码才能连接成功;

2.连接成功下面就可以进行数据的获取了,数据获取也是从网上找的工具类,下面贴上几个类的代码;

/**
 * 获取缓存中的考勤数据。配合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(){};
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(){};
}
/**
     * 读取考勤记录到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();
    }

至此几个工具类的代码都已经贴上了,工具类的方法都可以直接调用,而我的项目里只用到了读取用户信息和获取当天的考勤数据方法,大家可以自行尝试,下面贴上我自己的处理代码;

public void readZkemInfo(){

        logger.info("开始读取打卡机信息!");
        long startTime = System.currentTimeMillis();
        //连接打卡机(先设置密码,否则会报错)
        boolean password = ZkemSDKUtils.password(zkemPassword);
        boolean connect = ZkemSDKUtils.connect(zkemAddress, zkemPort);
        logger.info("打卡机连接:{}",connect);

        //调用读取信息到缓存的方法
        boolean readGeneralLogData = ZkemSDKUtils.readGeneralLogData();
        logger.info("读取打卡机信息到缓存:{}",readGeneralLogData);
        //如果连接打卡机和读取信息到缓存都没问题再去缓存中获取数据
        if(connect || readGeneralLogData){
            //获取打卡机所有的用户信息
            List<UserInfo> userInfo = ZkemSDKUtils.getUserInfo();
            //转化为JSON字符串
            String usersJsonString = JSON.toJSONString(userInfo);
            //反序列化对象
            List<UserInfo> userInfos = JSON.parseArray(usersJsonString, UserInfo.class);
            userInfos.forEach(System.out::println);
            for(UserInfo info : userInfos){
                String name = info.getName();
                Boolean enabled = info.getEnabled();
                String pwd = info.getPassword();
                Integer privilege = info.getPrivilege();
                String enrollNumber = info.getEnrollNumber();
                Integer userId = Integer.valueOf(enrollNumber);
				/**
				* 上面的都是打卡机的数据,可以根据自己的需求处理
				*/
            }

            //获取打卡机当天的考勤信息
            //ZkemSDKUtils.getGeneralLogData 从缓存中获取考勤信息
            List<Map<String, Object>> generalLogData = ZkemSDKUtils.getGeneralLogData();
//            logger.info("考勤信息:{}",generalLogData);
            String logDataJsonString = JSON.toJSONString(generalLogData);
            List<LogData> logDatas = JSON.parseArray(logDataJsonString, LogData.class);
            logDatas.forEach(System.out::println);
            for(LogData data : logDatas){
                //业务处理
                try{
                    //打卡机的时间
                    String time = data.getTime();
                    String enrollNumber = data.getEnrollNumber();
					/**
					* data有很多的数据,可以根据自己的业务逻辑拿想要的数据
					* 我这里只取了打卡时间和enrollNumber
 					*
					*/
                }catch(ParseException e){
                    e.printStackTrace();
                }
            }
        }
        //断开考勤机连接
        ZkemSDKUtils.disConnect();
        long endTime = System.currentTimeMillis();
        logger.info("读取打卡机信息结束,总耗时:{}毫秒",endTime - startTime);
    }

总结

到这里连接中控考勤机操作就结束了,方法有很多,待自己去探索,因为开发时间不足目前就是按照此逻辑处理的,后面有时间会再研究下,最开始连接打卡机因为摸了不少坑,一直连不上,后来按照上面方法慢慢尝试总算是可以了!
本文连接也是参考了一位大佬的博客,