通过 Android NFC 读取 ISO15693 RFID 标签导致数据输出不正确

Reading ISO15693 RFID tag through Android NFC results in incorrect data output

我们有一些过去使用 RFID reader 读取的 ISO15693 标签。今天我开始在 Android 上开发一个示例应用程序,使用 NfcV 和 Android 6 (API 23).

读取相同的标签

我能够从标签中读取一些数据,但数据中有一些意外的字符。这是我使用的代码:

private void readTagData(Tag tag) throws Exception {
    byte[] id = tag.getId();
    String strTag = new String(id, "UTF-8");
    boolean techFound = false;
    for (String tech : tag.getTechList()) {
        if (tech.equals(NfcV.class.getName())) {
            techFound = true;
            NfcV nfcvTag = NfcV.get(tag);
            try {
                nfcvTag.connect();
            } catch (IOException e) {
                Toast.makeText(this, "IO Exception", Toast.LENGTH_LONG).show();
                return;
            }
            try {
                int offset = 0;  
                int blocks = 19;  
                byte[] cmd = new byte[]{
                        (byte)0x60,                  
                        (byte)0x23,                  
                        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  // placeholder for tag UID
                        (byte)(offset & 0x0ff),      
                        (byte)((blocks - 1) & 0x0ff)
                };
                System.arraycopy(id, 0, cmd, 2, 8);
                byte[] response = nfcvTag.transceive(cmd);

                response = Arrays.copyOfRange(response, 0, 96);
                String strData = new String(response, "UTF-8");
                mTextView.setText("TAG:" + strTag + " DATA:" + strData);
            } catch (IOException e) {
                Toast.makeText(this, "An error occurred while reading", Toast.LENGTH_SHORT).show();
                return;
            }

            try {
                nfcvTag.close();
            } catch (IOException e) {
                Toast.makeText(getApplicationContext(), "Unable to close the connection!", Toast.LENGTH_SHORT).show();
                return;
            }
        }
    }
}

输出

标签 ID(UTF-8 解码):{�WP�

数据(UTF-8解码):����1ead��1234��5678��5000��00B1��2345��6181��5064��1602��2016��1603�� 2016��1602��2018��0011��8899��0002��0920��16����

十六进制表示的数据字节:

0000316561640031 3233340035363738
0035303030003030 42310032333‌43500
363138310035303‌6 3400313630320032
303‌1360031363033 0032303‌136003136
30320032303‌13800 303031310038383‌9
3900303030320030 393‌ 2300031360000

现在部分数据是正确的,但我不确定为什么会有这些“�”字符。标签 ID 也不正确。

另外,我尝试将字节数组 'response' 和标签 ID 转换为十六进制字符串,然后再转换为 ASCII,结果相同。

您收到的值是您发送的命令的预期响应:

您发送命令 READ MULTIPLE BLOCKS(命令代码 0x23)参数化以读取从偏移量 0 开始的 19 个块。您的标签的块大小似乎是 4 个字节。

此外,您指定了标志字节 0x60,它转换为标志 Address_flagOption_flag. Address_flag 使命令被寻址(即您必须指定目标标签的 UID,您可以正确执行)。 Option_flag 使标签 return 除了块数据本身之外,还成为块安全状态。因此,您的代码的响应如下所示:

+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+--------+-------+-------+-------+-------+
| FLAGS | BSS_0 | BLOCK_DATA_0                  | BSS_1 | BLOCK_DATA_1                  | ... | BSS_18 | BLOCK_DATA_18                 | 
+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+--------+-------+-------+-------+-------+

第一个字节,即响应标志,表示命令的总体结果(例如,在您的情况下,0x00 表示成功)。由于 Option_flag,每个数据块都以 BSS_x 字节(块安全状态)为前缀,这似乎是所有块的 0x00 .

由于您似乎对块安全状态不感兴趣,您不妨使用不带 Option_flag(标志 = 0x20)的命令:

byte[] cmd = new byte[]{
        (byte)0x20,                  
        (byte)0x23,                  
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  // placeholder for tag UID
        (byte)(offset & 0x0ff),      
        (byte)((blocks - 1) & 0x0ff)
};

那么,响应将是:

+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+-------+-------+-------+-------+
| FLAGS | BLOCK_DATA_0                  | BLOCK_DATA_1                  | ... | BLOCK_DATA_18                 | 
+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+-------+-------+-------+-------+

因此,为了从响应中提取数据块,您可以使用:

response = Arrays.copyOfRange(response, 1, 4 * blocks);

最后,将标签 ID 解码为 UTF-8 对于 ISO/IEC 15693 个标签来说根本没有意义。我不确定您期望那里有什么值,但您可能只想将 ID 的字节转换为它们的十六进制表示形式。