Search code examples
pythonarduinoformatnfcndef

How to send URL of a website to arduino in NDEF format using python?


I want to be able to send URI in NDEF format to my Arduino UNO which is connected to Sony's RC-S801 dynamic NFC tag. I used Hercules setup utility to send

"100101000300000000000000001b0030d102165370d1011255017374757474676172742e736f6e792e64650000000000"

as a hexadecimal string for http://www.stuttgart.sony.de and I was able to read it from my NFC enabled phone. But when I used the following python code, it didn't work:

import serial
import time

arduino = serial.Serial('COM6', 115200)
arduino.parity = 'M'
print arduino


print("writing")

input =    ("100101000300000000000000001b0030d102165370d1011255017374757474676172742e736f6e792e64650000000000")

arduino.write(input)                                


time.sleep(5)
print("stopped writing")



arduino.close() 

It shows as an empty record.Can anyone suggest changes to my python code that I should make in order to detect the NDEF message ?Here is the screenshot of the message that I get when I read the tag from my phone:

¨

This is my arduino code :

#include <EEPROM.h>
#define BUTTON_PIN 8 // Arduino Digital I/O pin where button is connected
#define NUM_OF_BLOCKS 14 // capacity of NFC Tag in 16-byte blocks

#include "FeliCaPlug.h"
#include <avr/pgmspace.h> <
#include <inttypes.h>

FeliCaPlug plug;

volatile byte dataStorage[NUM_OF_BLOCKS*16] = {
// TT3 Attribute block + NDEF Message Text Message 
0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x26,
0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

uint8_t blockData[NUM_OF_BLOCKS*16];
volatile uint8_t blinkCount = 1;
uint16_t numOfBlocks = NUM_OF_BLOCKS;

volatile boolean dataChanged = false;

void setup()
{ 
  Serial.begin(115200);
  uint8_t dfc[2] = {0xff, 0xe0};
  uint8_t userParam[4] = {0x01, 0x23, 0x45, 0x67};
  plug.initPort(); 
  plug.setParam(FELICA_PLUG_MODE_TYPE3, dfc, userParam);
  plug.setLEDPin(FELICA_PLUG_LED_PIN);
  for(int i = 0; i< NUM_OF_BLOCKS*16; i++)
     blockData[i] = dataStorage[i];
  plug.setBlockData(blockData, numOfBlocks, 0);
  plug.setFTWriteCallback(ftWriteCallback); // initialize write callback 
}

void loop()
{
  getFromUart();
  plug.doLoop();
  Serial.print(":");

  if(dataChanged){
    while(dataChanged)
    {
      Serial.println("NFC WRITING IN PROGRESS");
         // if the WriteF flag is OFF, writing type3 tag data has completed
          if(blockData[9] == 0x00)
          {
            Serial.println("NFC WRITING IS DONE"); //let's print complete memory written by external writer
            Serial.println("Recieved data from External writer:"); 

            Serial.println("<RAW_MEM>");

            for(int i = 0; i< NUM_OF_BLOCKS*16; i++)
            {
              Serial.print(blockData[i], HEX);
            }

            Serial.println("</RAW_MEM>");
          }
      //let's blink
      digitalWrite(FELICA_PLUG_LED_PIN, LOW);
      delay(50);
      digitalWrite(FELICA_PLUG_LED_PIN, HIGH);
      if(--blinkCount==0) dataChanged = false;
    }
    digitalWrite(FELICA_PLUG_LED_PIN, HIGH);
      delay(50);
  }

}



  byte index = 0;
  void getFromUart()
  {
    if(Serial.available() > 0)
    {
      while(Serial.available() > 0)
      {

          byte data = Serial.read();
          dataStorage[index] = data;     
          blockData[index] = dataStorage[index];
          plug.setBlockData(blockData, numOfBlocks, 0);
          index++;  
       }
       Serial.flush();
       Serial.println("Recieved data from UART:");
       Serial.println("<RAW_MEM>");

            for(int i = 0; i< NUM_OF_BLOCKS*16; i++)
            {
              Serial.print(blockData[i], HEX);
            }

        Serial.println("</RAW_MEM>");
    }
         index = 0; 
   }







void ftWriteCallback(uint16_t blockNum, uint8_t* data)
{ 

          // if the WriteF flag is 0x00, writing type3 tag data has started
          if(blockData[9] == 0x00)
          {
            Serial.println("NFC WRITING STARTED");
          }
  dataChanged=true;
  blinkCount=1;

   memcpy(blockData+blockNum*16, data, 16);
   }

Solution

  • While you are sending

    "100101000300000000000000001b0030d102165370d1011255017374757474676172742e736f6e792e64650000000000"
    

    as a hexadecimal byte string (i.e. as bytes with the hexadecimal values contained in the string) in your terminal program, you are sending it as an ASCII string in Python. So you effectively do the same as sending

    "313030313031303030333030303030303030303030303030303031623030333064313032313635333730643130313132353530313733373437353734373436373631373237343265373336663665373932653634363530303030303030303030"
    

    So, to get the same behavior in Python, you would have to convert the hexadecimal string into a byte array first:

    input_hex = "100101000300000000000000001b0030d102165370d1011255017374757474676172742e736f6e792e64650000000000"
    input = input_hex.decode("hex")
    

    Moreover, in order to make sure that the data is actually written, you may want to use something like

    arduino.write(input)
    arduino.flush()