通过 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 4231003233343500
3631383100353036 3400313630320032
3031360031363033 0032303136003136
3032003230313800 3030313100383839
3900303030320030 393 2300031360000
现在部分数据是正确的,但我不确定为什么会有这些“�”字符。标签 ID 也不正确。
另外,我尝试将字节数组 'response' 和标签 ID 转换为十六进制字符串,然后再转换为 ASCII,结果相同。
您收到的值是您发送的命令的预期响应:
您发送命令 READ MULTIPLE BLOCKS(命令代码 0x23)参数化以读取从偏移量 0 开始的 19 个块。您的标签的块大小似乎是 4 个字节。
此外,您指定了标志字节 0x60,它转换为标志 Address_flag 和 Option_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 的字节转换为它们的十六进制表示形式。
我们有一些过去使用 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 4231003233343500 3631383100353036 3400313630320032 3031360031363033 0032303136003136 3032003230313800 3030313100383839 3900303030320030 393 2300031360000
现在部分数据是正确的,但我不确定为什么会有这些“�”字符。标签 ID 也不正确。
另外,我尝试将字节数组 'response' 和标签 ID 转换为十六进制字符串,然后再转换为 ASCII,结果相同。
您收到的值是您发送的命令的预期响应:
您发送命令 READ MULTIPLE BLOCKS(命令代码 0x23)参数化以读取从偏移量 0 开始的 19 个块。您的标签的块大小似乎是 4 个字节。
此外,您指定了标志字节 0x60,它转换为标志 Address_flag 和 Option_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 的字节转换为它们的十六进制表示形式。