Closed jeffcrouse closed 6 years ago
Hi Jeff,
The ATR of your tag indicates you're using a mifare classic 1k (3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 01 00 00 00 00 6A). The iOS SDK supports mifare classic 1k tags but the cordova-plugin-flomio doesn't.
If you want to manually send APDUs to read the data in cordova you do this:
Load Auth: FF 82 00 00 06 FF FF FF FF FF FF
Auth block: FF 86 00 00 05 01 00
+ XX + 60 00
- where XX is the block you want to read
Read block: FF B0 00
+ XX + 10
- same XX as above
Let me know if you have any questions.
Thanks, Scott. That seems to work. Here is my code, in case anyone else needs it.
It would be helpful to note in the README which cards are supported by the plugin.
var block = "04";
var apdu = [
`FF 82 00 00 06 FF FF FF FF FF FF`,
`FF 86 00 00 05 01 00 ${block} 60 00`,
`FF B0 00 ${block} 10`].map(s=>{return s.replace(' ', '')});
flomioPlugin.sendApdu(this.deviceId, apdu[0], (response)=>{
flomioPlugin.sendApdu(this.deviceId, apdu[1], (response)=>{
flomioPlugin.sendApdu(this.deviceId, apdu[2], (payload)=>{
console.log(`!!! ${payload}`);
}, (error) => { console.log(`failed to send ${apdu[2]} ${error}`); });
}, (error) => { console.log(`failed to send ${apdu[1]} ${error}`); });
}, (error) => { console.log(`failed to send ${apdu[0]} ${error}`); });
Great, thanks for sharing your code and glad that worked for you.
Hey Scott -- can you let me know how to read from Mifare Ultralight?
readNdef should work with Mifare Ultralight, so no need to implement the APDUs yourself.
Here is what I am getting:
[1893:2322219] Change Status:Present
1893:2322219] ATR Response: 3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00 68
[1893:2322219] In transmitApdu acsbtreader
[1893:2322603] Command APDU:FF CA 00 00 00
[1893:2322219] Response Apdu: 04 4C 37 1A 71 40 81 90 00
[1893:2322219] In didReturnResponseApdu acsbtreader
[1893:2322219] Found tag UUID: 04 4C 37 1A 71 40 81 from device:RR464-001493
[1893:2322219] !! discovered tag: {"uid":"04 4C 37 1A 71 40 81 ","atr":"3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00 68"}
[1893:2322459] FmSessionManager sent apdu
[1893:2322459] In transmitApdu acsbtreader
[1893:2322603] Command APDU:FFB0000310
[1893:2322219] Response Apdu: E1 10 12 0F 01 03 A0 0C 34 03 12 D1 01 0E 54 02 90 00
[1893:2322219] FmSessionManager before sem
[1893:2322219] FmSessionManager after sem
[1893:2322219] command: FFB0000310, response: E1 10 12 0F 01 03 A0 0C 34 03 12 D1 01 0E 54 02 90 00
[1893:2322219] In didReturnResponseApdu acsbtreader
1893:2322459] FmSessionManager sent apdu
[1893:2322459] In transmitApdu acsbtreader
[1893:2322804] Command APDU:FFB0000410
[1893:2322219] Response Apdu: 01 03 A0 0C 34 03 12 D1 01 0E 54 02 65 6E 6B 69 90 00
[1893:2322219] FmSessionManager before sem
[1893:2322219] FmSessionManager after sem
[1893:2322219] command: FFB0000410, response: 01 03 A0 0C 34 03 12 D1 01 0E 54 02 65 6E 6B 69 90 00
[1893:2322219] In didReturnResponseApdu acsbtreader
[1893:2322219] !! onReadNdefFail Tag is not NDEF formatted
These tags were NDEF formatted and made read-only at the factory, and they work with another reader I have, so I'm not sure what is going on.
Hmm... that sounds like there's an issue with our parser. Do you have a hex dump of your NDEF data?
Not ideal, but to read data from Mifare Ultralight you can send these APDUs
async function readTagData(){
let numberOfPages = 16
let deviceId = "RR464-001493"
for (let page = 4; page <= numberOfPages; page += 4) {
let n = ''
page >= 16 ? n = '' + page.toString(16) : n = '0' + page.toString(16)
const nextApdu = 'FFB000' + n + '10'
const response = await flomioPlugin.sendApduWithPromise(deviceId, apdu)
}
}
Is there a way to get that with the Flomio reader? On the Arduino side I am using https://github.com/don/NDEF and this is what I get when I run "ReadTagExtended"
NFC Forum Type 2
UID: 04 4C 37 1A 71 40 81
This NFC Tag contains an NDEF Message with 1 NDEF Record.
NDEF Record 1
TNF: 1
Type: T
Payload (HEX): 02 65 6E 6B 69 73 73 20 2D 20 63 6F 6C 64 .enkiss - cold
Payload (as String): enkiss - cold
The problem is that the NDEF Message you want starts later than our parser handles.
This is your data: 01 03 A0 0C 34 03 12 D1 01 0E 54 02 65 6E 6B 69 73 73 20 2D 20 63 6F 6C 64
.
The NDEF parser wants D1 01 0E 54 02 65 6E 6B 69 73 73 20 2D 20 63 6F 6C 64
to behave correctly. Although this is a problem with our parser, in order to get you something working as soon as possible, use the above code to read your data and use
const records = flomioPlugin.ndef.decodeMessage(bytes);
to solve your issue.
An easier way to send the APDUs is to use flomioPlugin.readPage(deviceId, page)
seen here.
So you would call it like
async function readTagData(){
const numberOfPages = 16
const deviceId = "RR464-001493"
let tagData = ""
for (let page = 4; page <= numberOfPages; page += 4) {
const response = await flomioPlugin.readPage(deviceId, page)
tagData = tagData + response
}
const records = flomioPlugin.ndef.decodeMessage(tagData)
}
Let me know if this works for you.
So I'm calling readTagData() in flomioTagDiscovered right after I print out the result. I added console.log("!! NDEF", records); to the bottom of your function. This is what I get:
[2078:2372602] !! discovered tag: {"uid":"04 B7 2A 1A 71 40 80 ","atr":"3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00 68"}
[2078:2372649] FmSessionManager sent apdu
[2078:2372649] In transmitApdu acsbtreader
[2078:2372640] Command APDU:FFB0000410
[2078:2372602] Response Apdu: 01 03 A0 0C 34 03 12 D1 01 0E 54 02 65 6E 66 61 90 00
[2078:2372602] FmSessionManager before sem
[2078:2372602] FmSessionManager after sem
[2078:2372602] command: FFB0000410, response: 01 03 A0 0C 34 03 12 D1 01 0E 54 02 65 6E 66 61 90 00
[2078:2372602] In didReturnResponseApdu acsbtreader
[2078:2372649] FmSessionManager sent apdu
[2078:2372649] In transmitApdu acsbtreader
[2078:2372641] Command APDU:FFB0000810
[2078:2372602] Response Apdu: 74 65 20 2D 20 62 61 6E 67 FE 00 00 00 00 00 00 90 00
[2078:2372602] FmSessionManager before sem
[2078:2372602] FmSessionManager after sem
[2078:2372602] command: FFB0000810, response: 74 65 20 2D 20 62 61 6E 67 FE 00 00 00 00 00 00 90 00
[2078:2372602] In didReturnResponseApdu acsbtreader
[2078:2372649] FmSessionManager sent apdu
[2078:2372649] In transmitApdu acsbtreader
[2078:2372641] Command APDU:FFB0000c10
[2078:2372602] Response Apdu: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00
[2078:2372602] FmSessionManager before sem
[2078:2372602] FmSessionManager after sem
[2078:2372602] command: FFB0000c10, response: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00
[2078:2372602] In didReturnResponseApdu acsbtreader
[2078:2372649] FmSessionManager sent apdu
[2078:2372649] In transmitApdu acsbtreader
[2078:2372641] Command APDU:FFB0001010
[2078:2372602] Response Apdu: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00
[2078:2372602] FmSessionManager before sem
[2078:2372602] FmSessionManager after sem
[2078:2372602] command: FFB0001010, response: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 00
[2078:2372602] In didReturnResponseApdu acsbtreader
[2078:2372602] Change Status:Absent
upon further investigation, it's looking like "sendApduWithPromise" and "readPage" never return.
So I managed to brute force my way to an answer, but I don't fully understand it, which makes me nervous.
flomioPlugin.sendApdu(this.deviceId, 'FFB0000710', (result)=>{
var message = hex2a(result.replace(/ /g, "")).substr(2, 11);
console.log("!! message", message);
}, (error) => { console.log(`failed to send read command ${error}`); });
I was noticing that reading page by page, parts of the response would be repeated, which suggests that the "07" is not really a unique "page", but instead it is an offset, and then it gives you 16 bytes. Is this correct?
In my case (which I realize is somewhat specific), when I ask for "page" 7, I can convert the result to ASCII, and then take characters 2-11, and that is the string I want.
But, like I said, I don't understand why exactly, so if something gles wrong, I won't know how to fix it. Can you shed any light on what is going on here? For instance, why would the manufacturers of these tags (I don't know who they are - they are provided by my client) put the relevant NDEF data at such a weird offset?
Thanks much!
I believe it’s to do with (not often used) lock control TLV structures that the parser doesn’t handle. We will look into fixing it when we get a chance :)
You are correct about the read APDU, that's why we move up 4 pages at a time in the for-loop above. If you want more info about reading data / writing data using APDUs, this is a nice introduction article.
As I was saying before, the NDEF parser wants D1 01 0E 54 02 65 6E 6B 69 73 73 20 2D 20 63 6F 6C 64
from your data to behave correctly.
const records = flomioPlugin.ndef.decodeMessage(bytes);
will return a NDEF object similar to that returned by the Arduino library.
I used the Flomio iOS SDK with a FloBLE Plus to write a URL to a few tags that I have and then I successfully read it back.
and
This successfully writes back out http://www.cnn.com
But when I try to read the NDEF information from these same cards using the cordova plugin, the callbacks are never called.
Here is my TagDiscoveredListener
The two console.log messages are printed out, but then I just get:
Any ideas why this might happen?