I'm developing software for an Android Things device with RFID reader RC522. I use this library: https://github.com/Galarzaa90/android-things-rc522
My task querying the RC533 RFID reader:
protected Boolean doInBackground(Object... params) {
mRc522.stopCrypto();
while (true) {
........
byte[] uuid = mRc522.getUid();
return mRc522.selectTag(uuid);
}
}
In my activity I use this to convert the UID value into a string:
String tagRC522 = toHexString(mRc522.getUid(), "")
Another application in our ecosystem used to scan the NFC tags on an Android smartphone:
public void onNewIntent(Intent intent) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String tagNFC = bytesToHex(tagFromIntent.getId());
....
}
Other apps from Play Store (e.g. NFC Tools) give the same results as the code of the smartphone app above.
The problem I face now is that the value tagRC522
(on the Android Things device using RC522) does not match the value tagNFC
(in the smartphone app).
Tag1 tagRC522 = 45DOD86528 tagNFC = 45DOD865 Tag2 tagRC522 = 3567500103 tagNFC = 35675001 Tag3 tagRC522 = 88046f12F1 tagNFC = 046F12CA193A84 Tag4 tagRC522 = 3EBA46D517 tagNFC = 3EBA46D5
Why are the results between the two applications different? How must I change my Android Things code? Android mobile is production code and a many data in firebase in tagNFC version, I couldn't change that.
The results are essentially the same for the RC522 and Android's built-in NFC reader. The main differences are that the library that you use for the RC522
This means that only the first 4 bytes of the value obtained through mRc522.getUid()
are the UID value. The last (5th byte) is the XOR checksum over the previous 4 bytes. This is the BCC byte from the raw anti-collsion frame. If you want to calculate that for the value received through tagFromIntent.getId()
, you could do something like this:
byte[] uid = tagFromIntent.getId();
byte[] uidWithBCC = new byte[5];
for (int i = 0; i < 4; ++i) {
uidWithBCC[i] = uid[i];
uidWithBCC[4] ^= uid[i];
}
Similarly, in order to turn the value from mRc522.getUid()
into the value from tagFromIntent.getId()
, you could just drop the last byte:
byte[] uidWithBCC = mRc522.getUid();
byte[] uid = new byte[4];
for (int i = 0; i < 4; ++i) {
uid[i] = uidWithBCC[i];
}
Moreover, for tags with a double or tripple size UID, the value returned by mRc522.getUid()
is the value raw response of the PICC to casecade level 1 anti-collision. Consequently, it consists of the cascade tag (0x88) followed by the first 3 bytes of the UID, followed by the BCC. Hence, if you want to map the value that you received through tagFromIntent.getId()
to the value obtained from mRc522.getUid()
, you need to extract the first 3 bytes of the UID, prepend the cascade tag and append the BCC:
byte[] uid = tagFromIntent.getId();
if (uid.length > 4) {
uid[0] = (byte)0x88;
}
byte[] trimmedUidWithBCC = new byte[5];
for (int i = 0; i < 4; ++i) {
trimmedUidWithBCC[i] = uid[i];
trimmedUidWithBCC[4] ^= uid[i];
}
Unfortunately, this cannot easily be done the other way round. The missing bytes on the Android Things/RC522 side are not something that you could easily calculate from the other bytes. Instead, you would need to modify the library to perform further cascade levels in the anti-collision procedure. Only then you will be able to obtain the complete double and tripple size UIDs.