This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NDEF Records With Custom Title (mime type) ??? eg MEDIA: type/mymimetype not simply 'text/plain'

Hi

My application uses NFC for various reasons, and I need, at runtime to load up to 4 textural NDEF records onto the Nordic NRF 52832's NFC hardware.

If I wanted a simple text record or a URL record, this is, of course simple, but I use the tag content in an Intent Filter in Android to launch a specific app, and have that app perform a specific function based on the tag content. I am also supporting both iOS and Android pairing via NFC (obviously non-standard as iOS does not do standard NFC pairing). The android intent filter on NFC filters on the record title, not the record content - eg the blemacaddress in the screenshot below.

Please see the tag-scan (from Android NFC Tools app) which shows how I need the data to show up on the tag, and if you know how to achieve this, please shout - I can find no examples beyond text, url, pairing etc. When using the 'Media' type, what follows is the specific MIME-type, that, in my case is the 'ppa/blemacaddress'

My android intent filter in the MainActivity is thus:

[IntentFilter(
new [] {"android.nfc.action.NDEF_DISCOVERED"},
Categories=new[] {Intent.CategoryDefault},
DataMimeType = StaticDefs.Nfc.ProteusFixedIdentUuid,
DataPathPattern = StaticDefs.Nfc.ProteusFixedIdentUuidPayload)] //NB - dont appear to be able to filter on the payload apart from for standard NDEF record like URL.

PS: If this is a terrible way to achieve what I am trying to achieve then I guess I will just do it as a text record!

Nigel

  • Sorted this  by duplicating the nfc_text_rec.c/h files renamed to nfc_media_rec.c/h This essentially gives you a key/value pair for each NDEF record.

    See below...

    nfc_media_rec.c

    #include "sdk_common.h"
    
    #include <string.h>
    #include "nfc_media_rec.h"
    #include "nrf_error.h"
    
    #define TEXT_REC_STATUS_SIZE          1     ///< Size of the status.
    #define TEXT_REC_STATUS_UTF_POS       7     ///< Position of a character encoding type.
    #define TEXT_REC_RESERVED_POS         6     ///< Reserved position.
    
    
    /**
     * @brief Function for calculating payload size.
     */
    __STATIC_INLINE uint32_t nfc_media_rec_payload_size_get(nfc_media_rec_payload_desc_t * p_nfc_rec_media_payload_desc)
    {
        return (TEXT_REC_STATUS_SIZE
              + p_nfc_rec_media_payload_desc->lang_code_len
              + p_nfc_rec_media_payload_desc->data_len);
    }
    
    ret_code_t nfc_media_rec_payload_constructor(nfc_media_rec_payload_desc_t * p_nfc_rec_media_payload_desc,
                                                uint8_t                     * p_buff,
                                                uint32_t                    * p_len)
    {
        if ((p_nfc_rec_media_payload_desc->lang_code_len == 0)
         || (p_nfc_rec_media_payload_desc->lang_code_len & (1 << TEXT_REC_RESERVED_POS))
         || (p_nfc_rec_media_payload_desc->lang_code_len & (1 << TEXT_REC_STATUS_UTF_POS))
         || (p_nfc_rec_media_payload_desc->p_lang_code   == NULL)
         || (p_nfc_rec_media_payload_desc->data_len      == 0)
         || (p_nfc_rec_media_payload_desc->p_data        == NULL)
         || (p_len                                      == NULL))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        uint32_t payload_size = (nfc_media_rec_payload_size_get(p_nfc_rec_media_payload_desc)-2);
    
        if (p_buff != NULL)
        {
            if (payload_size > *p_len)
            {
                return NRF_ERROR_NO_MEM;
            }
    
            memcpy(p_buff,
                p_nfc_rec_media_payload_desc->p_data,
                p_nfc_rec_media_payload_desc->data_len);
        }
    
        *p_len = payload_size;
    
        return NRF_SUCCESS;
    }
    

    nfc_media_rec.h

    /**@file
     *
     * @defgroup nfc_text_rec Text records
     * @{
     * @ingroup  nfc_ndef_messages
     *
     * @brief    Generation of NFC NDEF MEDIA record descriptions.
     *
     */
    
    #include "nfc_ndef_record.h"
    
    /**
     * @brief Type of the Unicode Transformation Format.
     *
     * Values to specify the type of UTF for an NFC NDEF Text record.
     */
    typedef enum
    {
        UTF_8   = 0, ///< Unicode Transformation Format 8.
        UTF_16  = 1, ///< Unicode Transformation Format 16.
    } nfc_media_rec_utf_type_t;
    
    /**
     * @brief Text record payload descriptor.
     */
    typedef struct
    {
        nfc_media_rec_utf_type_t utf;    ///< Type of the Unicode Transformation Format.
    
        uint8_t const * p_lang_code;    ///< Pointer to the IANA language code.
        uint8_t         lang_code_len;  ///< Length of the IANA language code.
    
        uint8_t const * p_data;         ///< Pointer to the user text.
        uint32_t        data_len;       ///< Length of the user text.
    } nfc_media_rec_payload_desc_t;
    
    /**
     * @brief Constructor for an NFC NDEF Text record payload.
     *
     * @param[in]       p_nfc_rec_text_payload_desc Pointer to the Text record description.
     * @param[out]      p_buff                      Pointer to the payload destination. If NULL, function will
     *                                              calculate the expected size of the Text record payload.
     *
     * @param[in,out]   p_len                       Size of the available memory to write as input.
     *                                              Size of the generated record payload as output.
     */
    ret_code_t nfc_media_rec_payload_constructor(nfc_media_rec_payload_desc_t * p_nfc_rec_media_payload_desc,
                                                uint8_t                     * p_buff,
                                                uint32_t                    * p_len);
    
    /**
     *@brief Macro for creating and initializing an NFC NDEF record descriptor for a Text record.
     *
     * This macro creates and initializes an instance of type @ref nfc_ndef_record_desc_t and
     * an instance of type @ref nfc_text_rec_payload_desc_t, which together constitute
     * an instance of a Text record.
     *
     * Use the macro @ref NFC_NDEF_TEXT_RECORD_DESC to access the NDEF Text record descriptor instance.
     *
     * @param[in] NAME              Name of the created record descriptor instance.
     * @param[in] UTF               Unicode Transformation Format.
     * @param[in] P_LANG_CODE       Pointer to the IANA language code.
     * @param[in] LANG_CODE_LEN     Length of the IANA language code.
     * @param[in] P_MIME_DATA       Pointer to MIME data (eg the record title)
     * @param[in] MIME_DATA_LEN     The length of P_MIME_DATA
     * @param[in] P_PAYLOAD_DATA    Pointer to the data for the record payload
     * @param[in] PAYLOAD_DATA_LEN  The length of PAYLOAD_DATA_LEN
     */
    #define NFC_NDEF_MEDIA_RECORD_DESC_DEF(NAME,                                 \
                                          UTF,                                  \
                                          P_LANG_CODE,                          \
                                          LANG_CODE_LEN,                        \
    																			P_MIME_DATA,                            \
    																			MIME_DATA_LEN,                          \
                                          P_PAYLOAD_DATA,                        \
                                          PAYLOAD_DATA_LEN)                      \
        nfc_media_rec_payload_desc_t NAME##_nfc_media_rec_payload_desc =        \
        {                                                                       \
            .utf            = UTF,                                              \
            .p_lang_code    = P_LANG_CODE,                                      \
            .lang_code_len  = LANG_CODE_LEN,                                    \
            .p_data         = P_PAYLOAD_DATA,                                           \
            .data_len       = PAYLOAD_DATA_LEN,                                         \
        };                                                                      \
        NFC_NDEF_GENERIC_RECORD_DESC_DEF(NAME,                                  \
                                         TNF_MEDIA_TYPE,                        \
                                         P_LANG_CODE,                           \
                                         LANG_CODE_LEN,                         \
                                         P_MIME_DATA,                          \
                                         MIME_DATA_LEN,                         \
                                         nfc_media_rec_payload_constructor,      \
                                         &(NAME##_nfc_media_rec_payload_desc))
    		
    /**
     * @brief Macro for accessing the NFC NDEF Text record descriptor
     * instance that was created with @ref NFC_NDEF_TEXT_RECORD_DESC_DEF.
     */
    #define NFC_NDEF_MEDIA_RECORD_DESC(NAME) 	 NFC_NDEF_GENERIC_RECORD_DESC(NAME)
    
    
    
    

    Called in the same way as for text records, thus:

    static uint8_t ndef_msg_buf[256];
    
    //List of NDEF MIME Identifiers 
    const uint8_t PatientAppFixedId_Mime[] = {'p', 'p', 'a', '/', '8', '6', '2', '5', '8', '0', 'e', '2','-', 'd',   //Used to launch android intent
                                          	      '4', '6', 'f','-', '3', '0', '0', '8','-', '2', '3', '8', '0',     //Must be 1st record on tag
    													                    '-', '5', '4', '8', 'c', '4', '1', 'c', '9', 'a', '2', '0', 'c'};  //Used to qualify tag as 'for proteus app'
    
    //const  uint8_t TechAppFixedId_RecordId[] = {todo fill in GUID};
    																							
    const uint8_t ProteusTestConUuid_Mime[] = {'p', 'p', 'a', '/', 't', 'e', 's', 't', 'c', 'o', 'n', 'i', 'd'};                       //ppa/testconid
    const uint8_t ProteusMacAddress_Mime[] =  {'p', 'p', 'a', '/', 'b', 'l', 'e', 'm', 'a', 'c', 'a', 'd', 'd', 'r', 'e', 's', 's'};   //ppa/blemacaddress
    const uint8_t ProteusTagType_Mime[] 	=    {'p', 'p', 'a', '/', 't', 'a', 'g', 't', 'y', 'p', 'e'};                                //ppa/tagtype
    
    
    //List of Record content strings
    static const uint8_t PatientAppFixedUuid[] 	= {'7', '1', 'a', '1', '6', '8', '3', '9',  '-', '8', 'f', '4', '9', '-', '3', 'f', 'd', 'b',  
    																				       '-',	'0', '4', '8', '5', '-', 'c', 'c', '2', 'a', 'f', '6', '1', '3', '6', 'e', 'c', '0'};
    static const uint8_t Proteus_TagType_Text[] = {'B', 'l', 'e', 'C', 'o', 'n', 'n', 'e', 'c', 't'};
    
    static const uint8_t ident_code[] = {NULL};							/**< en_code[] = language code. Left blank intentionally. */
    
    void nfc_init()
    {
    	/* Set up NFC */
    		uint32_t  err_code;
        err_code = nfc_t2t_setup(nfc_callback, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    ret_code_t ConfigureTagForNfcPairing(uint8_t *ProteusMacAddr)
    {
        ret_code_t err_code;
    	
    	  //NFC_NDEF_TEXT_RECORD_DESC_DEF(PatientAppFixedId_NAME,UTF_8,ident_code,sizeof(Ident_code),PatientAppFixedId_RecordId,sizeof(PatientAppFixedId_RecordId));
    																	
    		//err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),&NFC_NDEF_TEXT_RECORD_DESC(PatientAppFixedId_NAME));
    	
    		//uint8_t *payload = GetTextBytesFromHex(ProteusMacAddr,MAC_ADDR_LEN);
    	
    		//uint8_t size = sizeof(payload);
    	
    		//Add the Guid record - this is what the Android intent uses to launch the app
    	  NFC_NDEF_MEDIA_RECORD_DESC_DEF(nfc_Proteus_GUID_rec,UTF_8,ident_code,sizeof(ident_code),PatientAppFixedId_Mime,sizeof(PatientAppFixedId_Mime),PatientAppFixedUuid,sizeof(PatientAppFixedUuid));
    	
    		//Add the MAC Address
    		NFC_NDEF_MEDIA_RECORD_DESC_DEF(nfc_Proteus_MacAddress_rec,UTF_8,ident_code,sizeof(ident_code),ProteusMacAddress_Mime,sizeof(ProteusMacAddress_Mime),(uint8_t*)GetStringFromHex(ProteusMacAddr, MAC_ADDR_LEN),MAC_ADDR_LEN*2);
    	
    		//NFC_NDEF_MEDIA_RECORD_DESC_DEF(nfc_Proteus_GUID_rec,UTF_8,ident_code,sizeof(ident_code),(uint8_t*)GetStringFromHex(ProteusMacAddr, MAC_ADDR_LEN),MAC_ADDR_LEN*2);
    				
    		NFC_NDEF_MSG_DEF(nfc_text_msg, 4);
    																
    	  err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),&NFC_NDEF_MEDIA_RECORD_DESC(nfc_Proteus_GUID_rec));			
    		err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_text_msg),&NFC_NDEF_MEDIA_RECORD_DESC(nfc_Proteus_MacAddress_rec));			
    																
    		uint32_t  len = sizeof(ndef_msg_buf);
    		err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_text_msg),ndef_msg_buf,&len);
    	
    		VERIFY_SUCCESS(err_code);
    	
    		err_code = nfc_t2t_payload_set(ndef_msg_buf, len);
        APP_ERROR_CHECK(err_code);
    
        /* Start sensing NFC field */
        err_code = nfc_t2t_emulation_start();
        APP_ERROR_CHECK(err_code);
    }
    

Related