node-pn532 icon indicating copy to clipboard operation
node-pn532 copied to clipboard

Card emulation

Open Zhairgling opened this issue 8 years ago • 44 comments

Can we transfer data between 2 pn532 ? like android beam ? I have a raspberry pi 3 and Pn532 from adafruit in uart mode.

Zhairgling avatar Jan 24 '17 10:01 Zhairgling

I saw here (https://github.com/techniq/node-pn532/blob/emulate-tag/src/pn532.js) that there was a function intended to make emulation of code but when I test I am a little lost.

I want to clarify that I already manage to read and write on tags.

Zhairgling avatar Jan 24 '17 13:01 Zhairgling

Hi @Zhairgling. The PN532 has the ability to be a writer as well as a reader, and I spent some time on the emulate-tag branch trying to get writing to work, but ultimately never had time to finish it. I also wasn't sure if being a simple writer was the same as Android Beam (if the later is more bi-directional communication). I do see Seeed Studios C library supports card emulation and snep (which I believe relates to Android Beam). I don't see me getting time to look at this for a while, but I accept PRs :). Between the User Guide and Datasheet (linked at the bottom of the README) and looking at Seeed Studio's implementation, it might not be too difficult to finish up.

techniq avatar Jan 24 '17 13:01 techniq

First of all thank you @techniq for the answer. I do not want to communicate with an android device. I refer to this system of operation only as an example. I am only trying to exchange a json object between two pn532. Can you tell me what was not working when you were working.

Zhairgling avatar Jan 24 '17 13:01 Zhairgling

I also see Adafruit's PN532 C++ library has a PR to add tag emulation. You might take a look at the changes and see what needs to be done. Most of it comes down to getting the command structure correct.

techniq avatar Jan 24 '17 13:01 techniq

To be honest, I don't remember exactly (it's been a little while). I remember I was trying to use my Android phone with NFC Tools to scan my pn532 breakout board but I think I was having trouble understanding how to attach the payload of the data to send.

techniq avatar Jan 24 '17 13:01 techniq

Thank you for the advices you gave me. I'm a little lost though. I think I'll come back to you if I have any questions. But I confess that I am afraid of not being able to make it work.

Zhairgling avatar Jan 24 '17 13:01 Zhairgling

Looking at the SimpleTag.ino file within the test scripts on the Adafruit PR, it looks like you need to first initialize (nfc.TgInitAsTarget()) and then setup a response buffer/handler (nfc.TgGetData(...)) and then ultimately send the data (nfc.TgSetData(...))

#include <Adafruit_PN532.h>

#define SCK     (2)
#define MOSI    (3)
#define SS      (4)
#define MISO    (5)

boolean TgInit = false;

Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);

void setup() {
  Serial.begin(115200);
  nfc.begin();

  uint8_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.println("Didn't find PN532 on RX board!");
    while (1); //halt
  }

  nfc.SAMConfig();
  Serial.println("Boards initialized and ready...");
}

void loop() {
  uint8_t sendbuf[] = {0x04, 0x03, 0x02, 0x01};
  uint8_t resbuf[16];
  uint8_t reslen;
  if(nfc.TgInitAsTarget()) {
    Serial.println("Tag Emulation Successful");
    if(!nfc.TgGetData(resbuf, &reslen)) {
      Serial.println("GetData Fail");
    }
    nfc.TgSetData(sendbuf, sizeof(sendbuf));
    Serial.print("Response: ");
    nfc.PrintHex(resbuf, reslen);
    Serial.println("Sent data: ");
    nfc.PrintHex(sendbuf, sizeof(sendbuf));
//    while(1);
  }
  delay(1000);
}

I think I was on the right track with emulateTag (i.e. TgInitAsTarget), emulateGetData (i.e. TgGetData) and emulateSetData (i.e. TgSetData) but maybe not knowing I needed to call all 3 each time to setup the transfer...

Looking at what I had done, I think I was using Seeed Studio's emulatetag.cpp as reference, trying to figure it out. If you want to give it a shot, I would work from their impl. and see where `node-pn532' is lacking.

techniq avatar Jan 24 '17 14:01 techniq

Page 21 of the User Manual titled ISO/IEC14443-4 PICC emulation concept and pages 151-165 on TgInitAsTarget, TgGetData, and TgSetData might come in handy, but ultimately working by example (Seeed/Adafruit impl.) will probably give you the best idea on how to implement.

I wish I had more time to look at this, but as of right now, just giving comments/feedback is the best I can do (for a while at least).

techniq avatar Jan 24 '17 14:01 techniq

Hello, I bent over it tonight. I prepared two PI and two pn532. They work well both. I even was able to test the emulation function of tag in the shell with the examples of the libnfc. I have needed a tip to choose the best way to implement it in the pn532 module. Should I load the old branch of your work or implement it myself in the latest version of the module?

Zhairgling avatar Jan 25 '17 10:01 Zhairgling

I would definitely use the master branch and not the old branch. Will make merging easier.

On Wed, Jan 25, 2017, 5:35 AM Zhairgling [email protected] wrote:

Hello, I bent over it tonight. I prepared two PI and two pn532. They work well both. I even was able to test the emulation function of tag in the shell with the examples of the libnfc. I have needed a tip to choose the best way to implement it in the pn532 module. Should I load the old branch of your work or implement it myself in the latest version of the module?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/techniq/node-pn532/issues/12#issuecomment-275074312, or mute the thread https://github.com/notifications/unsubscribe-auth/AAK1RIPxRZdO1CJa84nGKkqECvfEzQ6eks5rVyWIgaJpZM4LsF1P .

techniq avatar Jan 25 '17 11:01 techniq

I am currently working on it but I do not see very well the interest of the emulateSetData () function. Since there is one of the two configured as target the other just has to write on it, then reverse !?

Zhairgling avatar Jan 25 '17 13:01 Zhairgling

Can you explain me the switch in the emulateGetData() function ?

emulateGetData() {
        logger.info('Emulate get data...');
        return this.sendCommand([c.COMMAND_TG_GET_DATA])
        .then((frame) => {
            var body = frame.getDataBody();
            logger.debug('Frame data from emulate get data read:', util.inspect(body));
            var status = body[0];
            if (status === 0x13) {
                logger.warn('The data format does not match to the specification.');
            }
            // var dataIn = body.slice(1, body.length - 1); // skip status byte and last byte (not part of memory)
            // 00 00 a4 04 00 07 d2 76 00 00 85 01 01 00 26
            var cla = body[1]
            var instruction = body[2];
            var parameter1 = body[3];
            var parameter2 = body[4];
            var commandLength = body[5];
            var data = body.slice(6, commandLength);
            logger.debug('instruction', instruction);
            logger.debug('parameter1', parameter1);
            logger.debug('parameter2', parameter2);
            logger.debug('commandLength', commandLength);
            logger.debug('data', util.inspect(data));
            switch(instruction) {          ////////              <==========================
                case c.ISO7816_SELECT_FILE:
                    logger.info('Select file');
                    if (parameter1 === 0x00) {
                        logger.info('Select by Id');
                    }
                    if (parameter1 === 0x04) {
                        logger.info('Select by name');
                    }
                 /*   case C_APDU_P1_SELECT_BY_ID:
                        if(p2 != 0x0c){
                            DMSG("C_APDU_P2 != 0x0c\n");
                           // setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
                        } else if(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){
                           // setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
                            if(rwbuf[C_APDU_DATA+1] == 0x03){
                                currentFile = CC;
                            } else if(rwbuf[C_APDU_DATA+1] == 0x04){
                                currentFile = NDEF;
                            }
                        } else {
                           // setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
                        }
                        break;
                        case C_APDU_P1_SELECT_BY_NAME:
                        const uint8_t ndef_tag_application_name_v2[] = {0, 0x7, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
                        if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){
                           // setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
                        } else{
                            DMSG("function not supported\n");
                          //  setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
                        }
                        break;
                    break;*/
                case c.ISO7816_READ_BINARY:
                    logger.info('Read binary');
                    break;
                case c.ISO7816_UPDATE_BINARY:
                    logger.info('Update binary');
                    break;
                default:
                    logger.warn('Command not supported');
            }
            return data;
        });
    }

Zhairgling avatar Jan 25 '17 15:01 Zhairgling

I'll be honest, I'm not sure what it does :D.

I think at the time I copied Seeed Studio's C++ implementation and was slowly trying to break it down to understand it, but I didn't get that far... :(

I think it would be best if we scraped that and looked at Adafruit's PR C++ implementation for TgGetData since it looks to be simpler (and we can build it out after we have a better understanding...).

techniq avatar Jan 25 '17 15:01 techniq

I have worked on the emulateTag() function.

here is my work :

     emulateTag() {
        logger.info('Emulating tag...');
        var commAsTarget= 0x8C;
        var mode = 0x05; // PICC only, Passive Only
        var sens_res = [0x08, 0x00];
        var nfcId1t = [0x12, 0x34, 0x56];
        var sel_res = [0x60];
        var mifareParams = [].concat(sens_res, nfcId1t, sel_res);
        var felicaParams = [0,0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,0,
                           0,0];
        var nfcId3t = [0,0,0,0,0,0,0,0,0,0];
        var generalBytesLength = 0;
        var historicalBytesLength =  0;
        var commandBuffer = [
            commAsTarget,
            mode,
            mifareParams,
            felicaParams,
            nfcId3t,
            generalBytesLength,
            historicalBytesLength
        ];
        console.log('commandBuffer : '+ commandBuffer);
        return this.sendCommand(commandBuffer)
            .then((frame) => {

            var body = frame.getDataBody();
            logger.debug('body', util.inspect(body));
            var mode = body[0];
            console.log('mode', mode);
            logger.debug('mode', mode);
           
        });
    }
    

but i can't have any response by the pn532 after send the commandBuffer.

Zhairgling avatar Jan 26 '17 11:01 Zhairgling

Hmm, could you show me how you're calling emulateTag() and run your example with logging enabled:

PN532_LOGGING=debug node examples/emulate_tag.js

Replacing emulate_tag.js with whatever you called your file.

techniq avatar Jan 26 '17 13:01 techniq

I'm simply calling it like that in my index.js file :


var SerialPort = require('serialport').SerialPort;

//ndef = require('ndef');
var serialPort = new SerialPort('/dev/ttyAMA0', { baudrate: 115200 });
var rfid = new pn532.PN532(serialPort);
rfid.on('ready', function() {
console.log('rfid ready');
rfid.emulateTag();
    });

when I run with logging enabled i get that :


DEPRECATION: Please use `require('serialport')` instead of `require('serialport').SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
rfid ready
info: [pn532] Emulating tag...
commandBuffer : 140,5,8,0,18,52,86,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
debug: [pn532] Sending buffer: <Buffer 00 00 ff 08 f8 d4 8c 05 00 00 00 00 00 01 00>

Zhairgling avatar Jan 26 '17 13:01 Zhairgling

Hmm, looking at the logs for the buffer being sent (last line)

00 00 ff 08 f8 d4 8c 05 00 00 00 00 00 01 00

The command is incorrect (or is being truncated). The command buffer we build for each different type of command (in this case, TgInitAsTarget) is passed to sendCommand and is wrapped into a frame, which adds things such as the PREAMBLE, START_CODE_1 / 2, calculates and appends the data length and the checksum of the data length, the direction of the communication (to/from the PN532), the actual data we're trying to send (commandBuffer), the checksum of that data, and the POSTAMBLE. You can see all of this by looking at DataFrame, and particularly these lines:

toBuffer() {
        var array = [].concat([
            PREAMBLE,
            START_CODE_1,
            START_CODE_2,
            this.getDataLength(),
            this.getDataLengthChecksum(),
            this.getDirection()
        ],  this._data, [
            this.getDataChecksum(),
            POSTAMBLE
        ]);
        return new Buffer(array);
    }

I think testing and fixing to make sure new DataFrame(commandBuffer) produces the correct output should get you past this issue. If you look at page 150 of the user manual you can see the structure of the frame for a TgInitAsTarget frame (this only shows the direction (D4) and then everything within the data part.

Also, when you paste code/logs, if you could wrap them in triple single quotes (`) it would make reading them much easier 😄.

Hopefully you can track down the flaw in the building of DataFrame. It's likely we're taking for granted the type of data we've sent up to this far and some adjustments / special handling for this frame needs to occur.

I've had it on my backlog for a while, but I really need to get around to setting up some testing infrastructure (jest, mocha, ...) to make this type of development easier. Early on I thought it would be difficult to test since it was dependent on hardware / physical setup, but there is a lot of the code that could be tested without hardware, most importantly the building of the frames.

techniq avatar Jan 26 '17 14:01 techniq

I think I might see the issue in your code...

var commandBuffer = [
  commAsTarget,
  mode,
  mifareParams,
  felicaParams,
  nfcId3t,
  generalBytesLength,
  historicalBytesLength
];

Things such as mifareParams, felicaParams, etc are arrays within the commandBuffer array, but commandBuffer should be a "flat array" of all the data. I think you need to concat all of this together so commandBuffer.length === 38 (doing a quick count, I could be off by 1 or 2). It looks like currently DataFrame saw 8 as indicated in the logs (00 00 ff 08...), and makes since as your commandBuffer is a length of 7 and getDataLength() adds 1 to the commandBuffer (I forgot exactly way, but I think maybe to account for the data checksum byte).

Anyways, try to concat all of your command buffer together and let me know.

techniq avatar Jan 26 '17 14:01 techniq

Thanks..

I have concat my buffer command and it seems ok :

here the result of the emulate() function :

emulateTag() {
        logger.info('Emulating tag...');
        var commAsTarget= 0x8C;
        var mode = 0x05; // PICC only, Passive Only
        var sens_res = [0x08, 0x00];
        var nfcId1t = [0x12, 0x34, 0x56];
        var sel_res = [0x60];
        var mifareParams = [].concat(sens_res, nfcId1t, sel_res);

        var felicaParams = [0,0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,0,
                           0,0];

        var nfcId3t = [0,0,0,0,0,0,0,0,0,0];
        var generalBytesLength = 0;
        var historicalBytesLength =  0;
        var commandBuffer = [].concat(
            commAsTarget,
            mode,
            mifareParams,
            felicaParams,
            nfcId3t,
            generalBytesLength,
            historicalBytesLength
        );
        console.log('commandBuffer : '+ commandBuffer);
        return this.sendCommand(commandBuffer)
        .then((frame) => {
            var body = frame.getDataBody();
            logger.debug('body', util.inspect(body));
            var mode = body[0];
            console.log('mode', mode);
            logger.debug('mode', mode);
            // var initiatorCommand = ...
            // var numberOfTags = body[0];
            // if (numberOfTags === 1) {
            //     var tagNumber = body[1];
            //     var uidLength = body[5];
            //
            //     var uid = body.slice(6, 6 + uidLength)
            //     .toString('hex')
            //     .match(/.{1,2}/g)
            //     .join(':');
            //
            //     return {
            //         ATQA: body.slice(2, 4), // SENS_RES
            //         SAK: body[4],           // SEL_RES
            //         uid: uid
            //     };
            // }
        });
    }

and the result :

pi@raspberrypi:~/testNFCP2P $ PN532_LOGGING=debug node index.js
DEPRECATION: Please use `require('serialport')` instead of `require('serialport'                                                                               ).SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5                                                                                15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 f                                                                               e d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}                                                                               >
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","dat                                                                               a":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,                                                                               255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buf                                                                               fer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":2                                                                               1,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"                                                                               Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
rfid ready
info: [pn532] Emulating tag...
commandBuffer : 140,5,8,0,18,52,86,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                                                                               0,0,0,0,0,0,0,0,0
debug: [pn532] Sending buffer: <Buffer 00 00 ff 27 d9 d4 8c 05 08 00 12 34 56 60                                                                                00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0                                                                               0 00 00 00 97 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}                                                                               >
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","dat                                                                               a":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,                                                                               255,0]}>
debug: [frame-emitter] AckFrame found in buffer

when i use NFCTOOL from my phone i can read datas :D

Zhairgling avatar Jan 26 '17 15:01 Zhairgling

Hi ,

I'm now working on the emulateGetData() fonction:

    emulateGetData() {
        logger.info('Emulate get data...');

        return this.sendCommand([c.COMMAND_TG_GET_DATA])//0x86
        .then((frame) => {
            var body = frame.getDataBody();
            logger.debug('Frame data from emulate get data read:', util.inspect(body));
            var status = body[0];
            if (status === 0x13) {
                logger.warn('The data format does not match to the specification.');
            }
            // var dataIn = body.slice(1, body.length - 1); // skip status byte and last byte (not part of memory)
            // 00 00 a4 04 00 07 d2 76 00 00 85 01 01 00 26
            var cla = body[1]
            var instruction = body[2];
            var parameter1 = body[3];
            var parameter2 = body[4];
            var commandLength = body[5];
            var data = body.slice(6, commandLength);
            logger.debug('instruction', instruction);
            logger.debug('parameter1', parameter1);
            logger.debug('parameter2', parameter2);
            logger.debug('commandLength', commandLength);
            logger.debug('data', util.inspect(data));
            console.log('Final data read : '+data);
            return data;
        });
    }

used like that :

var pn532 = require('pn532');
var SerialPort = require('serialport').SerialPort;
//ndef = require('ndef');

var serialPort = new SerialPort('/dev/ttyAMA0', { baudrate: 115200 });
var rfid = new pn532.PN532(serialPort);

rfid.on('ready', function() {
	console.log('rfid ready');


	rfid.emulateTag()
	 rfid.emulateGetData().then(function(data) {
        console.log('dataRead : ', data);
    });
});

The output is :

pi@raspberrypi:~/testNFCP2P $ sudo PN532_LOGGING=debug node index.js
DEPRECATION: Please use `require('serialport')` instead of `require('serialport').SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
rfid ready
info: [pn532] Emulating tag...
commandBuffer : 140,5,8,0,18,52,86,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
debug: [pn532] Sending buffer: <Buffer 00 00 ff 27 d9 d4 8c 05 08 00 12 34 56 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 00>
info: [pn532] Emulate get data...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 02 fe d4 00 01 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer

What's wrong ? the AckFrame is not good ?

Zhairgling avatar Jan 27 '17 10:01 Zhairgling

You should wait for emulateTag()'s promise to resolve (wait on its ACK) before sending emulateGetData().

rfid.emulateTag().then(function() {
  console.log('emulateTag initialized');
  rfid.emulateGetData().then(function(data) {
  console.log('dataRead : ', data);
});

techniq avatar Jan 27 '17 12:01 techniq

Ok when i use ur code, I can't write with NFCTOOLS, that say " error when writing". When i use the rfid.writeNdefData(data) function :

var pn532 = require('pn532');
var SerialPort = require('serialport').SerialPort;
var ndef = require('ndef');

var serialPort = new SerialPort('/dev/ttyAMA0', { baudrate: 115200 });
var rfid = new pn532.PN532(serialPort);

rfid.on('ready', function() {
console.log('rfid ready');
 rfid.scanTag().then(function(tag) {
 	console.log('scan du taf');
        var messages = [
            ndef.uriRecord('http://www.google.com'),
            ndef.textRecord('test')
        ];
        console.log('messages: ',messages);
        var data = ndef.encodeMessage(messages);
        console.log('data: ',data);

        rfid.writeNdefData(data).then(function(response) {
            console.log('Write successful');
        });
    });
});

i get :

pi@raspberrypi:~/testNFCWrite $ PN532_LOGGING=debug node index.js
DEPRECATION: Please use `require('serialport')` instead of `require('serialport').SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
rfid ready
info: [pn532] Scanning tag...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 04 fc d4 4a 01 00 e1 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Data received <Buffer 00 00 ff 11 ef d5 4b 01>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 11 ef d5 4b 01>
debug: [frame-emitter] Data received <Buffer 01 00 08 60 04 08 12 34 56 05 75 33 92 03 8c 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 11 ef d5 4b 01 01 00 08 60 04 08 12 34 56 05 75 33 92 03 8c 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":75,"body":{"type":"Buffer","data":[1,1,0,8,96,4,8,18,52,86,5,117,51,146,3,140]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":75,"body":{"type":"Buffer","data":[1,1,0,8,96,4,8,18,52,86,5,117,51,146,3,140]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":75,"body":{"type":"Buffer","data":[1,1,0,8,96,4,8,18,52,86,5,117,51,146,3,140]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
debug: [pn532] body <Buffer 01 01 00 08 60 04 08 12 34 56 05 75 33 92 03 8c>
scan du taf
messages:  [ { tnf: 1,
    type: 'U',
    id: [],
    payload: [ 1, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109 ],
    value: 'http://www.google.com' },
  { tnf: 1,
    type: 'T',
    id: [],
    payload: [ 2, 101, 110, 116, 101, 115, 116 ],
    value: 'test' } ]
data:  [ 145,
  1,
  11,
  85,
  1,
  103,
  111,
  111,
  103,
  108,
  101,
  46,
  99,
  111,
  109,
  81,
  1,
  7,
  84,
  2,
  101,
  110,
  116,
  101,
  115,
  116 ]
info: [pn532] Writing data...
debug: [pn532] block: <Buffer 03 1a 91 01 0b 55 01 67 6f 6f 67 6c 65 2e 63 6f 6d 51 01 07 54 02 65 6e 74 65 73 74 fe>
debug: [pn532] Writing block: 0 at blockAddress: 4
debug: [pn532] pageData: <Buffer 03 1a 91 01>
info: [pn532] Writing block...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 09 f7 d4 40 01 a2 04 03 1a 91 01 96 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer

and on the target i have :

pi@raspberrypi:~/testNFCP2P $ PN532_LOGGING=debug node index.js
DEPRECATION: Please use `require('serialport')` instead of `require('serialport').SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
info: [pn532] Emulating tag...
commandBuffer : 140,5,8,0,18,52,86,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
debug: [pn532] Sending buffer: <Buffer 00 00 ff 27 d9 d4 8c 05 08 00 12 34 56 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Data received <Buffer 00 00 ff 05 fb d5 8d 08>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 05 fb d5 8d 08>
debug: [frame-emitter] Data received <Buffer e0 50 66 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 05 fb d5 8d 08 e0 50 66 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
debug: [pn532] body <Buffer 08 e0 50 66>
mode 8
debug: [pn532] mode 8
emulateTag initialized
info: [pn532] Emulate get data...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 02 fe d4 00 01 00>

It look like the target isn't waiting the good type of data.

Zhairgling avatar Jan 27 '17 13:01 Zhairgling

screenshot_2017-01-27-15-01-57 here is a screen of reading the target with nfcTool from android phone

Zhairgling avatar Jan 27 '17 14:01 Zhairgling

Nothing is jumping out at me so far. Receiving the 8D (141) command after the 8C (140) looks correct.

8C command mode (request): 5 (00000101)

  • not used (0000)
  • PICC only: yes (1)
  • DEP only: no (0)
  • Passive only: yes (1)

8D command mode (response): 8 (00001000):

  • not used (0)
  • Baudrate: 106 kbps (000)
  • ISO/IEC 14443-4 PICC: yes (1)
  • DEP: no (0)
  • Framing type : Mifare (00)

Actually as I've been looking at a bunch of other things, something just stood out at me. The last command...

debug: [pn532] Sending buffer: <Buffer 00 00 ff 02 fe d4 00 01 00>

It looks like it's sending 00 as the command for TgGetData instead of 86.


Actually it looks like:

emulateGetData() {
  return this.sendCommand([c.COMMAND_TG_GET_DATA]) //0x86

should be

emulateGetData() {
  return this.sendCommand([c.TG_GET_DATA]) //0x86

Sorry for the noise in the comment, I thought I would leave my train of thought (and I had already typed things before I figured more of it out) 😄

Btw, another Github comment tip: If you add js after the first triple backtick, it will add javascript syntax highlighting to your pasted code (ignore the ., I had to add it so it wouldn't be parsed and prematurely close the example:

.```js
// code here
.```

It supports a lot of other languages as well (I wouldn't put the js on our log output)

techniq avatar Jan 27 '17 15:01 techniq

Thank you for all advices you give me :) You are right, that was the wrong command. But when i provide the good one, it fail : And freez my pi


pi@raspberrypi:~/testNFCP2P $ PN532_LOGGING=debug node index.js
DEPRECATION: Please use `require('serialport')` instead of `require('serialport').SerialPort`
debug: [frame-emitter] listening to data
debug: [hsu] Initializing serial port...
debug: [hsu] Serial port initialized.
info: [pn532] Configuring secure access module (SAM)...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 05 fb d4 14 01 00 01 16 00>
debug: [hsu] Waking up PN532...
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 02 fe d5 15 16 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":21,"body":{"type":"Buffer","data":[22]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
info: [pn532] Emulating tag...
commandBuffer : 140,5,8,0,18,52,86,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
debug: [pn532] Sending buffer: <Buffer 00 00 ff 27 d9 d4 8c 05 08 00 12 34 56 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Data received <Buffer 00 00 ff 05 fb d5 8d 08>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 05 fb d5 8d 08>
debug: [frame-emitter] Data received <Buffer e0 50 66 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 05 fb d5 8d 08 e0 50 66 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":141,"body":{"type":"Buffer","data":[8,224,80,102]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
debug: [pn532] body <Buffer 08 e0 50 66>
mode 8
debug: [pn532] mode 8
emulateTag initialized
info: [pn532] Emulate get data...
debug: [pn532] Sending buffer: <Buffer 00 00 ff 02 fe d4 86 a6 00>
debug: [frame-emitter] Data received <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 00 ff 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [pn532] Response received for sendCommand <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
info: [pn532] Command Acknowledged <AckFrame {"type":"Buffer","data":[0,0,255,0,255,0]}>
debug: [frame-emitter] AckFrame found in buffer
debug: [frame-emitter] Data received <Buffer 00 00 ff 09 f7 d5 87 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 09 f7 d5 87 00>
debug: [frame-emitter] Data received <Buffer a2 04 03 1a 91 01 4f 00>
debug: [frame-emitter] Processing buffer <Buffer 00 00 ff 09 f7 d5 87 00 a2 04 03 1a 91 01 4f 00>
debug: [frame-emitter] Frame found in buffer
info: [frame-emitter] Frame <DataFrame {"data":{"command":135,"body":{"type":"Buffer","data":[0,162,4,3,26,145,1,79]}}}>
debug: [pn532] Response received for sendCommand <DataFrame {"data":{"command":135,"body":{"type":"Buffer","data":[0,162,4,3,26,145,1,79]}}}>
info: [pn532] Command Response <DataFrame {"data":{"command":135,"body":{"type":"Buffer","data":[0,162,4,3,26,145,1,79]}}}>
debug: [pn532] Removing listeners
debug: [frame-emitter] DataFrame found in buffer
debug: [pn532] Frame data from emulate get data read: <Buffer 00 a2 04 03 1a 91 01 4f>
debug: [pn532] instruction 4
debug: [pn532] parameter1 3
debug: [pn532] parameter2 26
debug: [pn532] commandLength 145
debug: [pn532] data <Buffer 01 4f>
Final data read : O
dataRead :  <Buffer 01 4f>

Zhairgling avatar Jan 27 '17 15:01 Zhairgling

Well, incremental progress 😄.

Hmm, so looking at the data of command 0x87 (135): 00 a2 04 03 1a 91 01 4f, it looks like the first byte is for status and is 00).

Looking at the User Manual, the following sections/pages look helpful:

  • 7.3.16 TgGetData (page 160)
  • 7.1 Error Handling (page 67)

I think a status of 00 is a good thing (otherwise it would be an error code from my understanding, but I just glossed over it).


It seems like you were breaking down the DataIn part of the 87 response (a2 04 03 1a 91 01 4f) into instruction, parameter1, etc. What exactly is failing (what are you expecting)?

techniq avatar Jan 27 '17 16:01 techniq

Yes :) For me it's failing because I can't get the data that i write with the other pn532, i try to exchange datas in ndef format. But i can't retrieve what i send

Zhairgling avatar Jan 27 '17 16:01 Zhairgling

You were writing the NDEF messages mentioned above right?

messages:  [ { tnf: 1,
    type: 'U',
    id: [],
    payload: [ 1, 103, 111, 111, 103, 108, 101, 46, 99, 111, 109 ],
    value: 'http://www.google.com' },
  { tnf: 1,
    type: 'T',
    id: [],
    payload: [ 2, 101, 110, 116, 101, 115, 116 ],
    value: 'test' } ]
data:  [ 145,
  1,
  11,
  85,
  1,
  103,
  111,
  111,
  103,
  108,
  101,
  46,
  99,
  111,
  109,
  81,
  1,
  7,
  84,
  2,
  101,
  110,
  116,
  101,
  115,
  116 ]

Looking at the user guide, it appears DataIn can be an array of data up to 262 bytes. Since you are trying to send more than this, I'm assuming it will need to come down in chunks/blocks, probably similarly to how readNdefData does. I do see 145 1 (or 91 01 in hex) in the your response, so that looks promising.

I don't fully understand what TgGetData and TgSetData are doing exactly TBH, although I think maybe TgSetData is used to confirm the receipt of the TgGetData.


In fact, looking at our data (response of ndef.encodeMessage(messages);, the length of the data array to send is 26, or 1a. Our response is:

  • 0x00/00: Status
  • 0xa2/162: Instruction (C_APDU_INS)
  • 0x04/4: Parameter 1 (C_APDU_P1)
    • C_APDU_P1_SELECT_BY_ID 0x00
    • C_APDU_P1_SELECT_BY_NAME 0x04
  • 0x03/3: Parameter 2 (C_APDU_P2)
  • 0x1a/26: Length command (C_APDU_LC)
  • 0x91/145: data[0]
  • 0x01/1: data[1]
  • 0x4f/79: checksum?

So my guess is we need to call TgSetData to acknowledge and probably TgGetData to get the next block of data. I don't know how we'll need to request the next block (maybe just calling TgGetData again. I think now's the time to break down how Seeed-Studio's EmulateTag::emulate works, with focus on the NDEF case statement (I saw ignore all the other case statements for now, just no-op them but leave placeholders so we know we need to handle them.

techniq avatar Jan 27 '17 17:01 techniq

I read a little more into Seeed-Studio's emulatetag.cpp and I don't believe the last byte (0x4f/79) is a checksum, but I'm not sure why it's not 11. It would be useful to:

  • Try sending a different NDEF message (and maybe 1 with a single message instead of 2)
  • Try to send the TgSetData command (8E). I'm not exactly sure of the payload for this command though.

I'm not sure how much more I can be right now. It would probably be helpful if you forked and committed your changes that way I can look at them as a whole (and maybe try to run it locally at some point if I get some time).

techniq avatar Jan 27 '17 20:01 techniq

Btw, I also have this spreadsheet that I created a while back to help me decipher NFC tag data / NDEF messages.

If you look at the second tab (NDEF Header) you'll see 91 in your data means this is the first of 2 records/messages, which is correct (since you're trying to send a url and a text record). The next byte 01 is the length of the record type indicator, which is typically always 1 (for well known types). The third byte should be the length of the NDEF message, which for the first message (google URL) is 11 (0x0B) but is in your logs as 4f, which I'm not sure why. It would be nice to capture logs a few times, a few with the same NDEF messages (to see if 4f changes) and a few with very simple payloads (maybe not even NDEF message, just a short byte array similar to Adafruit's test script mentioned above).

techniq avatar Jan 27 '17 20:01 techniq