Java读写EM4305卡、将4305卡制做成4100ID卡

news2025/1/9 20:41:19

        EM4305/EM4205卡是采用瑞士EM微电子公司工作频率为125kHz,具有读、写功能的非接触式RFID射频芯片,它具有功耗低、可提供多种数据传输速率和数据编码方法等特点,适合射频芯片ISO 11784/11785规范,该芯片被广泛应用于动物识别和跟踪、智能门锁、通道门禁等一卡通管理系统。

         EM4305/EM4205卡的EEPROM储存空间为512位,分为16个块,每个块32位,块1为UID块,块2为密码块,块4为配置块,块14、15为锁定标志块。可在-40℃~85℃在温度下工作。

         EM4305/EM4205卡可以修改其配置信息将其模拟成兼容EM4100的ID卡,可用于ID卡的复制,其内部存储结构如下图:

 

本示例使用的发卡器: EM4305 EM4469 ISO11784/85低频FXD-B动物标签AGV地标读写发卡器-淘宝网 (taobao.com)

 

import com.reader.ouridr;
public class Main {
    public static final byte NEEDSERIAL=1;  //只对指定UID列号的卡操作
    public static final byte NEEDKEY=2;     //需要用密码认证卡
    public static void main(String[] args) {
        if(args.length == 0) {
            System.out.println("\n请先输入运行参数!");
            System.out.println("\n参数 0:驱动读卡器嘀一声");
            System.out.println("\n参数 1:读取设备编号");
            System.out.println("\n参数 2:读取设备编号,输出字符串");
            System.out.println("\n参数 3:轻松读4100_ID卡");
            System.out.println("\n参数 4:轻松读4100_ID卡,卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡");
            System.out.println("\n参数 5:轻松读4100_ID卡,输出十位十进制卡号");
            System.out.println("\n参数 6:轻松读4100_ID卡,输出十位十进制卡号,卡在感应区时只能读一次");

            System.out.println("\n参数 7:写EM4205、4305卡配置值");
            System.out.println("\n参数 8:写EM4469、4569卡配置值");

            System.out.println("\n参数 9:轻松读Em4205、4305、4469、4569卡");
            System.out.println("\n参数 10:轻松写Em4205、4305、4469、4569卡");
            System.out.println("\n参数 11:修改Em4205、4305、4469、4569卡密钥");
            System.out.println("\n参数 12:锁定Em4205、4305、4469、4569块(谨慎使用!!!)");

            System.out.println("\n参数 13:将Em4205、4305卡制成4100ID卡");
            System.out.println("\n参数 14:轻松读HID卡");

            return;
        }

        //Java中只能使用string1.equals(string2)的方式来比较字符串
        if (args[0].equals("0")) {             //驱动读卡器发嘀一声
            System.out.print("\n0-驱动读卡器嘀一声\n");
            ouridr.beep(50);
            System.out.print("结果:如果能听到读卡器嘀一声表示成功,否则请检查读卡器是否已连上线!\n\n");
        }

        else if (args[0].equals("1")){           //读取设备编号,可做为软件加密狗用,也可以根据此编号在公司网站上查询保修期限
            int status;                          //存放返回值
            byte[] devicenumber = new byte[4];   //4字节设备编号

            System.out.print("\n1-读取设备编号\n");
            status = (int) (idreadertest.pcdgetdevicenumber(devicenumber) & 0xff);//& 0xff用于转为无符号行数据
            System.out.print("结果:");
            if (status == 0) {
                idreadertest.idr_beep(38);
                System.out.print("读取成功!设备编号为:" + (devicenumber[0] & 0xff) + "-" + (devicenumber[1] & 0xff) + "-" + (devicenumber[2] & 0xff) + "-" + (devicenumber[3] & 0xff));
            } else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("2")){            //读取设备编号,直接输出字符串
            System.out.print("\n2-读取设备编号\n");
            String statustr = idreadertest.pcdgetdevicenumber_str().trim();   //设备编号
            if(statustr.length()==10) {
                idreadertest.idr_beep(38);
                System.out.print("读取成功!设备编号为:" + statustr + "\n");
            }else{
                PrintErrStr(statustr);           //错误字符串代码提示
            }
        }

        else if (args[0].equals("3")){            //轻松读卡4100ID卡
            int status;                           //存放返回值
            byte[] mypiccserial  = new byte[5];   //5字节卡序列号

            System.out.print("\n3-轻松读卡\n");
            status = (int) (idreadertest.idr_read(mypiccserial ) & 0xff);          //只要卡在感应区,每次执行此方法都可以读到卡号
            System.out.print("结果:");
            if (status == 0) {
                idreadertest.idr_beep(38);
                String serialnumber = "";
                for (int i = 0; i < 5; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");

                long cardnum;
                cardnum=mypiccserial[4] & 0xff;
                cardnum=cardnum+(mypiccserial[3] & 0xff) *256;
                cardnum=cardnum+(mypiccserial[2] & 0xff) *65536;
                cardnum=cardnum+(mypiccserial[1] & 0xff) *16777216;
                long cardno10 = 0;
                for (int j=28; j>=0; j-=4) {
                    cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
                }
                System.out.print("换算成10进制卡号:"+String.format("%010d", cardno10)+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("4")){            //轻松读卡,卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            int status;                           //存放返回值
            byte[] mypiccserial  = new byte[5];   //5字节卡序列号

            System.out.print("\n4-轻松读一次卡\n");
            status = (int) (idreadertest.idr_read_once(mypiccserial ) & 0xff);   //卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            System.out.print("结果:");
            if (status == 0) {
                idreadertest.idr_beep(38);
                String serialnumber = "";
                for (int i = 0; i < 5; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");

                int cardnum;
                cardnum=mypiccserial[4] & 0xff;
                cardnum=cardnum+(mypiccserial[3] & 0xff) *256;
                cardnum=cardnum+(mypiccserial[2] & 0xff) *65536;
                cardnum=cardnum+(mypiccserial[1] & 0xff) *16777216;
                long cardno10 = 0;
                for (int j=28; j>=0; j-=4) {
                    cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
                }
                System.out.print("换算成10进制卡号:"+String.format("%010d", cardno10)+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("5")){            //读卡,输出十位十进制卡号
            System.out.print("\n5-读10进制卡号\n");
            String statustr = idreadertest.idr_read_8h10d_str().trim();        //只要卡在感应区,每次执行此方法都可以读到卡号
            if(statustr.length()==10) {
                idreadertest.idr_beep(38);
                System.out.print("读卡成功!8H10D卡号为:" + statustr + "\n");
            }else{
                PrintErrStr(statustr);   //错误字符串代码提示
            }
        }

        else if (args[0].equals("6")){            //读卡,输出十位十进制卡号,卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            System.out.print("\n6-读10进制卡号,只读一次\n");
            String statustr = idreadertest.idr_read_once_8h10d_str().trim();     卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            if(statustr.length()==10) {
                idreadertest.idr_beep(38);
                System.out.print("读卡成功!8H10D卡号为:" + statustr + "\n");
            }else{
                PrintErrStr(statustr);  //错误字符串代码提示
            }
        }

        else if (args[0].equals("7")){           //写EM4205、4305配置块
            System.out.print("\n7-写EM4205、4305卡配置值\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] configdata=new byte[4];       //配置值
            boolean withkey=false;               //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String oldKeyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            //EM4205、4305卡常用配置值说明
            //5F800100  数率RF/64、曼彻斯特码、 0-15块任意读.0-13块任意写,14-15块需密码写,卡片出厂默认配置值
            //5F800500  数率RF/64、曼彻斯特码、 0-1块任意读,3-15块需密码读,0-13块任意写,14-15块需密码写
            //5F801100  数率RF/64、曼彻斯特码、 0-15任意读,0-15块需密码写
            //5F801500  数率RF/64、曼彻斯特码、 0-1块任意读,3-15块需密码读,0-15块需密码写
            String configdatahex="5F800100";  //卡片出厂默认配置值,不同功能配置值不一样,请查询相关资料
            for (int i=0;i<4;i++){
                configdata[i]=(byte)Integer.parseInt(configdatahex.substring(i*2,(i+1)*2),16);
            }

            status = ouridr.em4305init(myctrlword,mypiccserial,oldpicckey,configdata);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex = "";
                for (int i = 0; i < 4; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("写EM4305卡配置块成功,16进制卡序列号:" + cardnohex + "\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("8")){           //写EM4469、4569配置块
            System.out.print("\n8-写EM4469、4569卡配置值\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] configdata=new byte[4];       //配置值
            boolean withkey=false;               //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String oldKeyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            //EM4469、4569卡常用配置值说明
            //45800100  数率RF/64、曼彻斯特码、 0-15块任意读.0-15块任意写,卡片出厂默认配置值
            //45800500  数率RF/64、曼彻斯特码、 0-1块任意读,3-15块需密码读,0-15块任意写
            //45801100  数率RF/64、曼彻斯特码、 0-15任意读,0-15块需密码写
            //45801500  数率RF/64、曼彻斯特码、 0-1块任意读,3-15块需密码读,0-15块需密码写
            String configdatahex="45800100";  //卡片出厂默认配置值,不同功能配置值不一样,请查询相关资料
            for (int i=0;i<4;i++){
                configdata[i]=(byte)Integer.parseInt(configdatahex.substring(i*2,(i+1)*2),16);
            }

            status = ouridr.em4469init(myctrlword,mypiccserial,oldpicckey,configdata);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex = "";
                for (int i = 0; i < 4; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("写EM4469卡配置块成功,16进制卡序列号:" + cardnohex + "\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("9")){           //读Em4205、4305、4469、4569卡
            System.out.print("\n9-读Em4205、4305、4469、4569卡\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] mypiccdata=new byte[100];     //读卡数据缓冲:卡无线转输分频比、卡内容长度(字节数),及最多返回12个块的数据
            byte[] mypiccblockflag=new  byte[2]; //指定本次操作的块
            boolean withkey=true;                //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String Keyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(Keyhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            String Seleblockstr0="00111011";  //从左到右依次表示第7、6、5、4、3、2、1、0块是否要操作,取1表示该块要读,取0表示该块不读,如要读0、1、3 块取值为 00001011,
            String Seleblockstr1="00000000";  //从左到右依次表示第15、14、13、12、11、10、9、8块是否要操作,取1表示该块要读,取0表示该块不读,如要读10、12、14 块取值为 01010100,
            mypiccblockflag[0]=(byte)Integer.parseInt(Seleblockstr0,2);
            mypiccblockflag[1]=(byte)Integer.parseInt(Seleblockstr1,2);

            status = ouridr.em4305read(myctrlword,mypiccserial,oldpicckey,mypiccblockflag,mypiccdata);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex="";
                for (int i=0;i<4;i++){
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length()) ;
                }
                System.out.print("读EM4305卡成功,16进制卡序列号:"+cardnohex+"\n");
                System.out.print("卡无线转输分频比:"+Integer.toString(mypiccdata[0])+"\n");
                if(mypiccdata[1]>0) {
                    String blockdata = "块内数据:";
                    for (int i = 0; i < mypiccdata[1]; i++) {
                        String bytestr = "00" + Integer.toHexString(mypiccdata[2 + i] & 0xff);
                        blockdata = blockdata + bytestr.substring(bytestr.length() - 2, bytestr.length()) + " ";
                    }
                    System.out.print(blockdata+"\n");
                }
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("10")){           //写Em4205、4305、4469、4569卡
            System.out.print("\n10-写Em4205、4305、4469、4569卡\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] mypiccdata=new byte[100];     //读卡数据缓冲:卡无线转输分频比、卡内容长度(字节数),及最多返回12个块的数据
            byte[] mypiccblockflag=new  byte[2]; //指定本次操作的块
            boolean withkey=true;                //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String Keyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(Keyhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            //写入的数据,实际写入数据的块由mypiccblockflag值决定,1块为UID已固化、2块为密钥块、4块为配置块、14、15为锁定标志块,都不能用此方式写
            String writedatahex="00000000333333335555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
            for (int i=0;i<28;i++){
                mypiccdata[i]=(byte)Integer.parseInt(writedatahex.substring(i*2,(i+1)*2),16);
            }

            String Seleblockstr0="00001000";  //从左到右依次表示第7、6、5、4、3、2、1、0块是否要操作,取1表示该块要写,取0表示该块不写,如要写3、5 块取值为 00101000,
            String Seleblockstr1="00000000";  //从左到右依次表示第15、14、13、12、11、10、9、8块是否要操作,取1表示该块要写,取0表示该块不写,如要写8、9、10 块取值为 00000111,
            mypiccblockflag[0]=(byte)Integer.parseInt(Seleblockstr0,2);
            mypiccblockflag[1]=(byte)Integer.parseInt(Seleblockstr1,2);

            status = ouridr.em4305write(myctrlword,mypiccserial,oldpicckey,mypiccblockflag,mypiccdata);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex="";
                for (int i=0;i<4;i++){
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length()) ;
                }
                System.out.print("写EM4305卡成功,16进制卡序列号:"+cardnohex+"\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("11")){          //修改Em4205、4305、4469、4569卡密钥
            System.out.print("\n11-修改Em4205、4305、4469、4569卡密钥\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] newpicckey=new byte[4];       //卡片新密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            boolean withkey=true;                //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定卡号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String oldKeyhexstr="00000000";   //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            String newKeyhexstr="00000000";     //新密钥
            for(int i=0;i<4;i++){
                newpicckey[i]=(byte)Integer.parseInt(newKeyhexstr.substring(i*2,(i+1)*2),16);
            }

            status = ouridr.em4305changekey(myctrlword,mypiccserial,oldpicckey,newpicckey);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex = "";
                for (int i = 0; i < 4; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("修改EM4305卡密钥成功,16进制卡序列号:" + cardnohex + "\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("12")){           //锁定Em4205、4305、4469、4569块
            System.out.print("\n12-锁定Em4205、4305、4469、4569块\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] mypiccblockflag=new  byte[2]; //指定本次操作的块
            boolean withkey=true;                //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String Keyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(Keyhexstr.substring(i*2,(i+1)*2),16);
                }
            }else{
                System.out.print("锁定块需要带密码操作!\n");
                return;
            }

            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            //块1为uid块,只能读取不需锁定!
            //块2为配置区,只能在初始化函数中操作不需锁定
            //14、15 块为锁定标志块,只能在初始化函数中操作不需锁定!
            String Seleblockstr0="00001000";  //从左到右依次表示第7、6、5、4、3、2、1、0块是否要操作,取1表示该块要锁定,取0表示该块不锁,如要锁3、5 块取值为 00101000,
            String Seleblockstr1="00000000";  //从左到右依次表示第15、14、13、12、11、10、9、8块是否要操作,取1表示该块要锁,取0表示该块不锁,如要锁8、9、10 块取值为 00000111,
            mypiccblockflag[0]=(byte)Integer.parseInt(Seleblockstr0,2);
            mypiccblockflag[1]=(byte)Integer.parseInt(Seleblockstr1,2);

            status = ouridr.em4305lock(myctrlword,mypiccserial,oldpicckey,mypiccblockflag);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex="";
                for (int i=0;i<4;i++){
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length()) ;
                }
                System.out.print("锁定EM卡块成功,16进制卡序列号:"+cardnohex+"\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("13")){           //将Em4205、4305卡制成4100ID卡
            System.out.print("\n13-将Em4205、4305卡制成4100ID卡\n");
            byte status;                         //存放返回值
            byte myctrlword=0;                   //控制字
            byte[] oldpicckey=new byte[4];       //认证密钥
            byte[] mypiccserial=new byte[4];     //卡UID序列号
            byte[] newpicckey=new byte[4];       //新密码
            byte[] mynewuid=new byte[5];         //新4100卡号
            boolean withkey=false;               //是否要认证卡密钥
            boolean thiscarduit =false;          //是否只操作指定UID序号的卡
            boolean addkey=false;                //是否要开启密钥保护写入信息

            if (withkey){  //本次操作需要密码验证,将认证密钥加入oldpicckey
                myctrlword=(byte)(myctrlword+NEEDKEY);
                String oldKeyhexstr="00000000";     //认证密钥
                for(int i=0;i<4;i++){
                    oldpicckey[i]=(byte)Integer.parseInt(oldKeyhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(thiscarduit){  //本次只操作指定UID号的卡,mypiccserial
                myctrlword=(byte)(myctrlword+NEEDSERIAL);
                String Uidhexstr="00000000";   //卡片uid
                for(int i=0;i<4;i++){
                    mypiccserial[i]=(byte)Integer.parseInt(Uidhexstr.substring(i*2,(i+1)*2),16);
                }
            }
            if(addkey){  //写入卡号后,是否要加密保护
                String newkeyhexstr="00000000";   //新密钥
                for(int i=0;i<4;i++){
                    newpicckey[i]=(byte)Integer.parseInt(newkeyhexstr.substring(i*2,(i+1)*2),16);
                }
            }

            int NewUid=123456789;              //要写入的4100十进制卡号
            byte[] UidByte=int2byte(NewUid);   //卡号转4字节数组
            mynewuid[0]=0x27;                  //首字节为厂商代码
            for (int i = 0; i < 4; i++) {      //4字节卡号
                mynewuid[1+i]=UidByte[i];
            }

            status = ouridr.em4305to4100(myctrlword,mypiccserial,oldpicckey,newpicckey,mynewuid);
            if(status == 0) {
                ouridr.beep(38);
                String cardnohex = "";
                for (int i = 0; i < 4; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    cardnohex = cardnohex + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("将EM4305卡配置成ID卡成功!\n");
            }else {
                PrintErrInf(status);   //错误代码提示
            }
        }

        else if (args[0].equals("14")){           //轻松读HID卡
            int status;                           //存放返回值
            byte[] mypiccserial  = new byte[7];   //7字节HID卡序列号缓冲

            System.out.print("\n14-轻松读HID卡\n");
            status = (int) (ouridr.hidread(mypiccserial ) & 0xff);          //只要卡在感应区,每次执行此方法都可以读到卡号
            System.out.print("结果:");
            if (status == 0) {
                ouridr.beep(38);
                String serialnumber = "";
                for (int i = 0; i < 7; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读取HID卡号成功!16进制卡序列号为:" + serialnumber+"\n");

                long cardnum;
                cardnum=mypiccserial[6] & 0xff;
                cardnum=cardnum+(mypiccserial[5] & 0xff) *256;
                cardnum=cardnum+(mypiccserial[4] & 0xff) *65536;
                cardnum=cardnum+(mypiccserial[3] & 0xff) *16777216;
                long cardno10 = 0;
                for (int j=28; j>=0; j-=4) {
                    cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
                }
                System.out.print("换算成10进制卡号:"+String.format("%010d", cardno10)+"\n");
            } else {
                PrintErrInf(status);   //错误代码提示
            }
        }


    }

    //---------------------------------------------------------------------------------整数转4字节数组
    public static byte[] int2byte(int res) {
        byte[] targets = new byte[4];
        targets[0] = (byte) (res & 0xff);// 最低位
        targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
        targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
        targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
        return targets;
    }

    //----------------------------------------------------------------------------------错误代码提示
    static void PrintErrInf(int errcode) {
        switch(errcode){
            case 1:
                System.out.print("错误代码:1,卡放得远 或 需要先认证密钥才能写卡!\n");
                break;
            case 2:
                System.out.print("错误代码:2,本卡尚未开启密码功能,函数myctrlword中无需加入NEEDKEY!\n");
                break;
            case 3:
                System.out.print("错误代码:3,需要密码才能读卡,函数myctrlword要加入NEEDKEY!\n");
                break;
            case 4:
                System.out.print("错误代码:4,卡放得远 或 需要密码才能读卡!\n");
                break;
            case 5:
                System.out.print("错误代码:5,密码错误!\n");
                break;
            case 8:
                System.out.print("错误代码:8,未寻到卡,请重新拿开卡后再放到感应区!\n");
                break;
            case 21:
                System.out.print("错误代码:21,没有动态库!\n");
                break;
            case 22:
                System.out.print("错误代码:22,动态库或驱动程序异常!\n");
                break;
            case 23:
                System.out.print("错误代码:23,驱动程序错误或尚未安装!\n");
                break;
            case 24:
                System.out.print("错误代码:24,操作超时,一般是动态库没有反映!\n");
                break;
            case 25:
                System.out.print("错误代码:25,发送字数不够!\n");
                break;
            case 26:
                System.out.print("错误代码:26,发送的CRC错!\n");
                break;
            case 27:
                System.out.print("错误代码:27,接收的字数不够!\n");
                break;
            case 28:
                System.out.print("错误代码:28,接收的CRC错!\n");
                break;
            default:
                System.out.print("未知错误,错误代码:"+Integer.toString(errcode)+"\n");
                break;
        }
    }

    //----------------------------------------------------------------------------------错误字符串代码提示
    static void PrintErrStr(String Errstr){
        if(Errstr.equals("ER08")){
            System.out.print("错误代码:ER08,未寻到卡,请重新拿开卡后再放到感应区!\n");
        } else if(Errstr.equals("ER22")){
            System.out.print("错误代码:ER22,动态库或驱动程序异常!\n");
        } else if(Errstr.equals("ER23")){
            System.out.print("错误代码:ER23,驱动程序错误或尚未安装!\n");
        } else if(Errstr.equals("ER24")){
            System.out.print("错误代码:ER24,操作超时,一般是动态库没有反映!\n");
        }else {
            System.out.print("错误代码:"+Errstr);
        }
    }

}
package com.reader;

public class ouridr {
    public native static byte beep(int xms);static{   //让设备发出声音
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4305init(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] configdata);static{  //写EM4305配置值,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4305read(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] blockflag,byte[] blockdata);static{  //读EM4305卡,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4305write(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] blockflag,byte[] blockdata);static{  //写EM4305卡,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4305changekey(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] newkey);static{  //修改EM4305卡密钥,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }


    public native static byte em4305lock(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] lockflag);static{  //锁定EM4305卡块数据 ,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4469init(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] configdata);static{  //写EM4469、4569卡配置值,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4305to4100(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] newkey,byte[] newIDbuf);static{  //将EM4305卡配置成ID4100卡,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte em4469tohid(byte ctrlword, byte[] mypiccserial,byte[] oldkey,byte[] newkey,byte[] newHIDbuf);static{  //将EM4460卡配置成ID、HID卡,
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

    public native static byte hidread(byte[] mypiccserial );static{    //读HID卡
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            System.load(System.getProperty("user.dir") + "/OUR_IDR.dll");
        } else if (osName.contains("nix") || osName.contains("nux")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.so");
        } else if (osName.contains("mac")) {
            System.load(System.getProperty("user.dir") + "/libOURIDR.dylib");
        }
    }

}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040692.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

传智教育引通义灵码进课堂,为技术人才教育学习提效

7 月 17 日&#xff0c;阿里云与传智教育在阿里巴巴云谷园区签署合作协议&#xff0c;双方将基于阿里云智能编程助手通义灵码在课程共建、品牌合作及产教融合等多个领域展开合作&#xff0c;共同推进 AI 教育及相关业务的发展&#xff0c;致力于培养适应未来社会需求的高素质技…

PyTorch之loading fbgemm.dll异常的解决办法

前言 PyTorch是一个深度学习框架&#xff0c;当我们在本地调试大模型时&#xff0c;可能会选用并安装它&#xff0c;目前已更新至2.4版本。 一、安装必备 1. window 学习或开发阶段&#xff0c;我们通常在window环境下进行&#xff0c;因此需满足以下条件&#xff1a; Windo…

tkinter绘制组件(43)——对话框

tkinter绘制组件&#xff08;43&#xff09;——对话框 引言布局窗口初始化对话框类型弹窗显示和窗口冻结内容返回信息提示输入对话框 函数封装 效果测试代码最终效果 github项目pip下载结语 引言 严格来说&#xff0c;对话框是控件的组合&#xff0c;不是一个控件&#xff0c…

AI菜鸟向前飞 — OpenAI Assistant API 原理以及核心结构(二)

AI菜鸟向前飞 — OpenAI Assistant API 原理以及核心结构&#xff08;一&#xff09; 使用Assistant API 如何去实现一个自定义“Tool” 依然是三步走&#xff0c;是不是很像&#xff1f;与LangChain定义的方式基本一致&#xff0c;请回看 AI菜鸟向前飞 — LangChain系列之十三…

详细分析SQL Server触发器的基本知识

目录 前言1. 基本知识2. Demo3. 查找特定表的存储过程 前言 原先写过一篇类似的&#xff0c;不过是基于Mysql&#xff1a;添加链接描述 对应Sql Server的补充知识点&#xff1a;详细配置SQL Server的链接服务器&#xff08;图文操作Mysql数据库&#xff09; 1. 基本知识 基…

JVM虚拟机(一)介绍、JVM内存模型、JAVA内存模型,堆区、虚拟机栈、本地方法栈、方法区、常量池

目录 学习JVM有什么用、为什么要学JVM&#xff1f; JVM是什么呢&#xff1f; 优点一&#xff1a;一次编写&#xff0c;到处运行。&#xff08;Write Once, Run Anywhere&#xff0c;WORA&#xff09; 优点二&#xff1a;自动内存管理&#xff0c;垃圾回收机制。 优点三&am…

IOS 03 纯代码封装自定义View控件

本节将通过纯代码进行封装自定义View控件&#xff0c;以常用的设置页的item为例&#xff0c;实现UI效果如下&#xff1a; 1、创建SettingView继承自UIView import UIKitclass SettingView: UIView {} 2、重写 init() 和 required init?(coder: NSCoder) 方法 纯代码创建Set…

仿RabbitMq实现消息队列正式篇(虚拟机篇)

TOC目录 虚拟机模块 要管理的数据 要管理的操作 消息管理模块 要管理的数据 消息信息 消息主体 消息的管理 管理方法 管理数据 管理操作 队列消息管理 交换机数据管理 要管理的数据 要管理的操作 代码展示 队列数据管理 要管理的数据 要管理的操作 代码展示…

PHP转Go系列 | ThinkPHP与Gin框架之打造基于WebSocket技术的消息推送中心

大家好&#xff0c;我是码农先森。 在早些年前客户端想要实时获取到最新消息&#xff0c;都是使用定时长轮询的方式&#xff0c;不断的从服务器上获取数据&#xff0c;这种粗暴的骚操作实属不雅。不过现如今我也还见有人还在一些场景下使用&#xff0c;比如在 PC 端扫描二维码…

浅谈JDK

JDK(Java Development Kit) JDK是Java开发工具包&#xff0c;是Java编程语言的核心软件开发工具。 JDK包含了一系列用于开发、编译和运行Java应用程序的工具和资源。其中包括&#xff1a; 1.Java编译器&#xff08;javac&#xff09;&#xff1a;用于将Java源代码编译成字节…

MS8923/8923S低压、高精度、推挽输出比较器

MS8923/8923S 是一款差分输入、高速、低功耗比较器&#xff0c;具 有互补 TTL 输出。其传输延时在 10ns 左右&#xff0c;输入共模范围可以 到负轨。 MS8923/8923S 可以在线性区保持输出稳定特性&#xff0c;单电 源供电是 5.0V &#xff0c;双电源供电是 5V 。 MS89…

【算法/学习】:记忆化搜索

✨ 落魄谷中寒风吹&#xff0c;春秋蝉鸣少年归 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;算法学习 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f44…

数据结构——队列的讲解(超详细)

前言&#xff1a; 我们在之前刚讲述完对于栈的讲解&#xff0c;下面我们在讲另一个类似栈的数据结构——队列&#xff0c;它们都是线性表&#xff0c;但结构是大有不同&#xff0c;下面我们直接进入讲解&#xff01; 目录 1.队列的概念和结构 1.1.队列的概念 1.2.队列的结构 2.…

基于Python的去哪儿网数据采集与分析可视化大屏设计与实现

摘要 本文旨在介绍如何利用Python进行去哪儿网景点数据的采集与分析。通过采集去哪儿网上的景点数据&#xff0c;我们可以获取大量的旅游相关信息&#xff0c;并基于这些数据进行深入分析和洞察&#xff0c;为旅游行业、市场营销策略以及用户个性化推荐等提供支持。 本文将使用…

MySQL(DQL)

一&#xff0c;SQL语言分类 &#xff08;1&#xff09;数据查询语言&#xff08;DQL&#xff1a;Data Query Language&#xff09;其语句&#xff0c;也称为 “数据检索语句”&#xff0c;用以从表中获得数据&#xff0c;确定数据怎样在应用程 序给出。关键字 SELECT 是 DQL&a…

Python打包命令汇总

1、pyinstaller打包 环境安装&#xff1a;pip install pyinstaller 网络不好可以通过 -i 指定安装源&#xff1a;pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple/安装完成后通过&#xff1a;pyinstaller --version 查看是否安装成功 打包单个脚本&…

操作系统笔记二

虚拟内存 把不常用的数据放到硬盘上去&#xff0c;常用的代码或者数据才加载到内存&#xff0c;来实现虚拟的大内存的感觉 覆盖技术 目标&#xff1a;在较小内存运行较大程序。 原理&#xff1a;把程序按自身逻辑结构划分若干功能上相对独立的程序模块。不回同时执行的模块共…

FreeRTOS学习笔记(一)—— 裸机和RTOS,Freertos移植(MDK),stm32cubeIDE使用Freertos

FreeRTOS学习笔记&#xff08;一&#xff09;—— 裸机和RTOS&#xff0c;Freertos移植&#xff08;MDK&#xff09;&#xff0c;stm32cubeIDE使用Freertos 文章目录 FreeRTOS学习笔记&#xff08;一&#xff09;—— 裸机和RTOS&#xff0c;Freertos移植&#xff08;MDK&#…

uniapp/vue个性化单选、复选组件

个性化单选和复选组件在网页设计中非常常见&#xff0c;它们不仅能够提升用户界面的美观度&#xff0c;还能改善用户体验。此组件是使用vue uniapp实现的个性化单选复选组件。设计完成后&#xff0c;点击生成源码即可。 拖动组件过设计区 每行显示数量 默认支持每行三个&#…

Maven-学习首篇

目录 Maven简介基本概念&特点Maven的安装与配置Maven基础概念及使用方法Maven的项目结构Maven的使用Maven的依赖管理Maven的生命周期和插件常见疑问Maven的插件机制是如何工作的&#xff1f;Maven的POM文件主要包含哪些内容&#xff1f;Maven的生命周期包括哪些阶段&#x…