Java 如何创建RFID应用程序来读取HID万能钥匙5427 CK

Java 如何创建RFID应用程序来读取HID万能钥匙5427 CK,java,rfid,smartcard-reader,Java,Rfid,Smartcard Reader,我和我的同事正在尝试创建一个Java程序,用一个HID万能键5427 CK读取卡片。我们以前没有使用RFID的经验,并检查: 对于一些示例代码(除此之外,我们还没有找到太多示例代码),我们已经对其进行了调整和使用,但是在运行代码时,我们得到了 java.nio.channels.UnresolvedAddressException at sun.nio.ch.Net.checkAddress(Unknown Source) at sun.nio.ch.SocketChannelImpl.con

我和我的同事正在尝试创建一个Java程序,用一个HID万能键5427 CK读取卡片。我们以前没有使用RFID的经验,并检查:

对于一些示例代码(除此之外,我们还没有找到太多示例代码),我们已经对其进行了调整和使用,但是在运行代码时,我们得到了

java.nio.channels.UnresolvedAddressException
at sun.nio.ch.Net.checkAddress(Unknown Source)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at org.apache.mina.transport.socket.nio.SocketConnector.connect(SocketConnector.java:187)
at org.apache.mina.transport.socket.nio.SocketConnector.connect(SocketConnector.java:137)
at org.apache.mina.common.support.BaseIoConnector.connect(BaseIoConnector.java:40)
at org.llrp.ltk.net.LLRPConnector.connect(LLRPConnector.java:135)
at org.llrp.ltk.net.LLRPConnector.connect(LLRPConnector.java:116)
at hellojavaltk.HelloJavaLtk.connect(HelloJavaLtk.java:212)
at hellojavaltk.HelloJavaLtk.run(HelloJavaLtk.java:227)
at hellojavaltk.HelloJavaLtkMain.main(HelloJavaLtkMain.java:9)​
代码基本上是:

public class HelloJavaLtkMain
{
public static void main(String[] args) throws InterruptedException
{
HelloJavaLtk app = new HelloJavaLtk();

System.out.println("Starting reader.");
app.run("HID-OMNIKEY-5427-CK");
Thread.sleep(30000);
System.out.println("Stopping reader.");
app.stop();
System.out.println("Exiting application.");
System.exit(0);
}
}
Hellojavatk是一个实现LLRPEndpoint接口的类,基本上是从上面的链接复制粘贴的

因此,我们不知道我们是否只是在运行时没有正确寻址设备(“HID-OMNIKEY-5427-CK”),或者在尝试到达该端点时是否应该做一些完全不同的事情

如果有人能够将OMNIKEY-5427-CK(或其他读卡器)与Java代码一起使用,可以向我们指出其他代码示例,或者让我们进一步了解我们做错了什么,我们将不胜感激


谢谢大家

HID OMNIKEY 5427 CK是一款兼容PC/SC(CCID)的智能卡读卡器。您尝试使用的库是为EPC RFID阅读器设计的。不过,该全键阅读器可通过PC/SC访问。当前的Oracle Java内置了使用访问PC/SC智能卡读卡器的支持。

我认为您使用的代码不兼容,因为它看起来与LLRP协议兼容,并且您的设备支持CCID和键盘楔块

CCID:

我找不到您的设备的文档,但是看起来CCID可能使用串行连接工作,如果是这种情况,您可以使用RXTX连接到设备(),然后发送命令并从中读取响应

这是一个小例子:

// change to right port
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier("/dev/ttyS0"); 
    if (portIdentifier.isCurrentlyOwned()) {
        throw new RfidReaderUnavailableException();
    } else {
        CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
        if (commPort instanceof SerialPort) {
            SerialPort serialPort = (SerialPort) commPort;
            // This details have to match your device configuration or it won't work
            serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);

            in = serialPort.getInputStream();
            out = serialPort.getOutputStream();

            <-- Here you write the commands on out and read the responses from in -->

        } else {
            System.out.println("Error: Only serial ports are handled by this.");
        }
   }
//更改为右端口
CommPortIdentifier-portIdentifier=CommPortIdentifier.getPortIdentifier(“/dev/ttyS0”);
if(portIdentifier.isCurrentlyOwned()){
抛出新的RfidReaderUnavailableException();
}否则{
CommPort CommPort=portIdentifier.open(this.getClass().getName(),2000);
if(串行端口的commPort实例){
SerialPort SerialPort=(SerialPort)commPort;
//此详细信息必须与您的设备配置相匹配,否则将无法工作
serialPort.setSerialPortParams(9600,serialPort.DATABITS_8,serialPort.STOPBITS_1,serialPort.PARITY_NONE);
serialPort.setFlowControlMode(serialPort.FLOWCONTROL_RTSCTS_输入| serialPort.FLOWCONTROL_RTSCTS_输出);
in=serialPort.getInputStream();
out=serialPort.getOutputStream();
}否则{
System.out.println(“错误:此操作仅处理串行端口”);
}
}
如果CCID不支持串行通信,他们必须为其提供驱动程序。如果驱动程序不具备Java兼容性,那么您需要编写一个JNI包装器,以便从Java代码中使用它

键盘楔块:


这种模式下的功能可能会被简化为像键盘一样写入卡id,就像条形码扫描仪一样。您将无法从键盘输入和读卡器中分辨,也无法从卡存储器中读取或写入数据,但这可能对您有效,具体取决于您的应用程序必须实现的功能。

我知道这是一个非常古老的问题,因为我在任何地方都找不到使用命令的工作示例,使用下面的代码,您可以获得卡的ATR和UID

TerminalFactory factory = TerminalFactory.getDefault(); 
List<CardTerminal> terminals = factory.terminals().list();
System.out.println("Terminals: " + terminals);
// get the first terminal
CardTerminal terminal = terminals.get(0);

// establish a connection with the card
Card card = terminal.connect("*");
System.out.println("card: " + card);
ATR atr = card.getATR();
System.out.println("Card ATR: " + DatatypeConverter.printHexBinary(atr.getBytes()));
CardChannel channel = card.getBasicChannel();
CommandAPDU commandAPDU;
commandAPDU = new CommandAPDU(new byte[]{(byte) 0xFF,(byte) 0xCA,(byte) 0x00,(byte) 0x00,(byte) 0x00});             
ResponseAPDU r = channel.transmit(commandAPDU);
System.out.println("Response: " + r.toString() + ", NR: " + r.getNr());
String hex = DatatypeConverter.printHexBinary(r.getBytes());
System.out.println("Response: " + hex);
System.out.println("Card UID: " + DatatypeConverter.printHexBinary(r.getData()));
byte[] copyOf = Arrays.copyOf(r.getBytes(), r.getNr());
System.out.println("Card UID from bytes: " + DatatypeConverter.printHexBinary(copyOf));
// disconnect
card.disconnect(false);
TerminalFactory工厂=TerminalFactory.getDefault();
列表端子=工厂.terminals().List();
System.out.println(“终端:+终端”);
//到达第一个终点站
CardTerminal=terminals.get(0);
//与卡建立连接
卡=终端。连接(“*”);
System.out.println(“卡:+卡”);
ATR ATR=card.getATR();
System.out.println(“卡ATR:+DatatypeConverter.printHexBinary(ATR.getBytes()));
CardChannel=card.getBasicChannel();
CommandAPDU CommandAPDU;
commandAPDU=newcommandapdu(新字节[]{(字节)0xFF,(字节)0xCA,(字节)0x00,(字节)0x00,(字节)0x00});
ResponseADU r=信道传输(commandAPDU);
System.out.println(“响应:+r.toString()+”,NR:+r.getNr());
字符串hex=DatatypeConverter.printHexBinary(r.getBytes());
System.out.println(“响应:+hex”);
System.out.println(“卡UID:+DatatypeConverter.printHexBinary(r.getData()));
byte[]copyOf=Arrays.copyOf(r.getBytes(),r.getNr());
System.out.println(“来自字节的卡UID:+DatatypeConverter.printHexBinary(copyOf));
//断开
卡。断开连接(错误);

谢谢。smartcardio.*成功了!我们成功连接到RFID读卡器并发送了APDU命令,该命令返回标记UID。@Diego Alonso您能为您的解决方案添加更多信息吗?我正在尝试发送
transmitAPDU(新命令apdu(新字节[]{(字节)0x80,(字节)0xA6,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00,(字节)0x00})但接收到
sun.security.smartcardio.pcsce异常:未知错误0x1f
@Diego:您介意分享您的解决方案吗。我在为omnikey 5427CK找到正确的APDU时遇到了问题。Skumar,我已经很久没有参与这件事了。我相信源代码是共享的。我不记得是DDS SmartCardio还是SampleLoginWindow。这是一个实验,编码它的人是一个生物医学工程师。我希望它能帮助你,但我不能保证你会在那里找到解决问题的办法。祝你好运。谢谢,尽管我们的读者似乎没有能力通过串口进行交流。