3

我正在处理的应用程序需要尽快(最多 500 毫秒)检测到卡已从现场移除。

这是我为测试检测卡缺失所需的时间所做的工作:

public static long timeToGetCardAbsent(int version) throws CardException{
    TerminalFactory factory = TerminalFactory.getDefault();

    CardTerminals terminalList = factory.terminals();
    CardTerminal ct = terminalList.list().get(0);

    long connectTime = 0, disconnectTime = 0;

    ct.waitForCardPresent(0);
    connectTime = new Date().getTime();

    ct.waitForCardAbsent(0);
    disconnectTime = new Date().getTime();

    return disconnectTime - connectTime;
}

当程序运行时,我在读卡器上点击一张(DESFire)非接触式卡并立即将其取出。

以下是输出:

1437
1437
1438
1437
1422

我的意思是读卡器(或程序?)需要将近 1.5 秒才能检测到卡不存在,这对我来说太长了。

有没有办法加快这种检测?我目前正在使用javax.smartcardio,我会用另一个库获得更好的结果吗?我实际上不知道我还能用什么,你有线索吗?

谢谢, GChabot

4

2 回答 2

1

我今天实际上设法改善了很多检测时间。我正在查看“NFC Wizard”中的那个网页,并注意到他们在检测我的卡移除方面非常快。这个 javascript 网页通过一个 Java 小程序与读者进行通信,所以它实际上只使用了我所拥有的。

NFC Wizard 的创建者 SpringCard 实际上在该页面的 Other resources > Java 和“SpringCard PC/SC SDK (ZIP archive)”下提供了类似应用程序的完整文档甚至源代码。

在浏览他们的代码时,我注意到在对卡执行操作后,使用该card.disconnect(false);功能(我曾尝试使用card.disconnect(true);但结果与以前相同......运气不好)。

所以这就是我现在要做的:

import java.util.Date;
import javax.smartcardio.*;

public class NewMethod {
    private long connectTime = -1;
    private long disconnectTime = -1;

    private TerminalFactory factory;
    private CardTerminals terminalList;
    private CardTerminal ct;

    public NewMethod() throws CardException{
        factory = TerminalFactory.getDefault();

        terminalList = factory.terminals();
        ct = terminalList.list().get(0);
    }

    public long waitForCardPresent(){
        try {
            ct.waitForCardPresent(0);
        } catch (CardException e) { }
        return new Date().getTime();
    }

    public long waitForCardAbsent(){
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e1) { }

            try{
                ct.connect("*").disconnect(false);
            }
            catch(Exception e) {
                return new Date().getTime();
            }
        }
    }

    public void run(){
        while(true){
            connectTime = waitForCardPresent();
            disconnectTime = waitForCardAbsent();
            System.out.println((disconnectTime-connectTime));
        }
    }

    public static void main(String[] args){
        NewMethod nm;
        try {
            nm = new NewMethod();
            nm.run();
        } catch (CardException e) {
            e.printStackTrace();
        }
    }
}

(线程部分是可选的,但无论有没有它我都得到了相同的结果,所以我更愿意节省一点处理器消耗)

这是我使用线程版本的时间:这里是非线程版本531, 437, 656, 657, 735, 657, 547, 844, 15, 766, 859, 563, 765, 562, 422, 437, 563, 562, 562, 672, 672, 16, 547, 546, 672, 15, 344984, 547, 796, 656, 796, 718, 656, 812, 625, 781, 813, 547, 797, 532, 407, 609, 719, 328, 469, 328, 0, 546, 625, 0, 843, 703

我们可能会注意到结果非常不稳定(实际上使用线程版本要好得多),这可能来自我将卡敲击读卡器的方式,但我相信这不是唯一的原因。

现在看起来对我来说已经足够好了。我只是希望当我在我的应用程序中实际使用它时不会有太大的变化。

于 2012-08-03T16:26:53.307 回答
0

我在 Linux 上进行了一些测试,在 Linux 中,默认的 PCSC守护进程每 400-500 毫秒轮询一次驱动程序。如果我发现的 PCSC Lite 信息正确,不稳定的驱动程序似乎会删除此轮询并使用不同的方法。

Java 方法似乎几乎立即返回,所以这不太可能是罪魁祸首。尝试将您的 PCSC 实施、固件和驱动程序更新到最新版本。如果这不起作用,您将别无选择解决它。

这个答案确实让我在 Linux 上安装了 PCSC + SCM SDI010 驱动程序安装和 3 个固件的测试。但无论如何,我自己也想要这些信息。如果我得到更新版本的 PCSC lite 工作,我会更新答案。

于 2012-08-02T21:47:49.857 回答