Edited at

【NFC】NDEFについて理解する

More than 1 year has passed since last update.

NDEF(NFC Data Exchange Format)についてまとめる機会があったのでその忘備録として

NDEFとはNFCを介してFeliCaやMIFARE、さらにiOS11にて提供が開始されるCore NFCなどへデータを読み書きするデータフォーマットを指す。

殆どの場合はライブラリなどを通じてデータの読み書きを行うがNDEFそのものに触れる機会があったのでNDEFとはどういう構造なのかをまとめていこうと思う。

公式のスペックはこちら。

http://nfc-forum.org/our-work/specifications-and-application-documents/specifications/nfc-forum-technical-specifications/


NDEFの構造を理解する


NDEF Message編

NDEFは1つのNDEF Messageと呼ばれるコンテナに、1~n個のNDEF Recordを含む。

このNDEF Record 1つに対してURLやテキストなどのデータを記録していく。

実装する際、このNDEF Messageを取り扱うか(NDEF Recordのみで良い場合等)は実装する環境に依存するので、この項目を無視することができるかもしれない…。

NEDFはデータ構造においてTLV方式を採用している。Tag Length Valueの3つ組で、Tagの部分にデータ型を指定し、Length部分にOctet長を、Valueのところに実際の値をいれるというデータ構造。

無題.png

NFC対応のICまたは機器(以下"タグ"と表記)に書き込みを行う場合、NDEF Messageの総容量がタグのPAYLOADの容量を超えてはならない。

例えば、こちらのタグであれば144Byte以内に収めなければならない。

よほど大容量の記録が行えるタグを除き、基本は1つのタグに1つのNDEF Recordで精一杯だと思う。

NDEF Messageのデータ構造は下図のとおりに表される。(NFC Forum Type 2 Tagの場合)

無題.png

1バイト目にNDEFであることを示す識別子0x03を指定し、2バイト目にNDEF Recordの容量(単位:バイト)を符号なし8bit整数で、そして3バイト目以降にNDEF Recordを記録する。

ちなみに、識別子はNFC Forum Type 2 Tagの場合だと以下が存在する。

識別子
名称
説明

0x00
NULL TLV
NULLです。特になし。メモリ領域の調整用

0x01
Lock Control TLV
ロック対象のビットを設定する。

0x02
Memory Control TLV
予約されたメモリ領域を識別する。

0x03
NDEF Message TLV
NDEF Messageのコンテナ

0xfd
Proprietary TLV
専有情報にタグを付ける。

0xfe
Terminator TLV
終端コード。データの終りを示す。


NDEF Record編

NDEF Recordは複数の設定情報を含んだHEADER領域と本体データを含んだPAYLOAD領域が存在する。

NDEF Recordのデータ構造を下図に表記する。青がHEADERや終端指定コード、オレンジがPAYLOADを示す。

無題.png

各要素の説明がこちら

要素
説明

MB (Message Begin)
NDEF Messageの始まりを意味するフラグ

ME (Message End)
NDEF Messageの終わりを意味するフラグ

CF (Chunked Flag)
分割されたNDEF Messageの一部を示すフラグ

SR (Short Flag)
255Byte以下のRecordを意味するフラグ。有効にするとPAYLOAD LENGTHが4Byteから1Byteになる。

IL (ID Length)
IDが設定されていることを示す。無効にするとID LENGTHとIDを省略することができる。

TNF (Type Name Format)
TYPEフィールドの種類を示す。3bitで指定する。詳細は別図参照。

TYPE LENGTH
TYPEフィールドの長さを符号なし8bit整数で指定する。この値でTYPEフィールドの容量が決定する。

PAYLOAD LENGTH

SRの値に応じて長さが変化する。PAYLOADフィールドの長さを符号なしビックエンディアンで指定する。この値でPAYLOADフィールドの容量が決定する。

ID LENGTH

ILの値に応じて省略されることがある。IDフィールドの長さを符号なし8bit整数で指定する。この値でIDフィールドの容量が決定する。

TYPE
TYPE LENGTHに応じて長さが変化する。TNFの値によって設定値が変わる。

ID

ILの値に応じて省略されることがある。ID LENGTHに応じて長さが変化する。

PAYLOAD
PAYLOAD LENGTHに応じて長さが変化する。TNFとTYPEによって内容が変わる。

TNFの設定内容はこちら


説明

0x00
Empty

0x01
NFC Forun well-known-type

0x02
Media-type as define in RFC2046

0x03
Absolute URI as define in RFC3986

0x04
NFC Forum external type

0x05
Unknown

0x06
Unchanged

0x07
Recerved


TNFとPAYLOAD

TNFの値に応じて、TYPEで設定できる内容とPAYLOAD内のデータ構造が変化する。

今回はNFC Forun well-known-typeを例として取り上げる。

NFC Forun well-known-typeではTypeとPAYLOADにRTD(Record Type Difinition)が使用される。

RTDで使用できる種類で代表的なものはこちら。

分類
TYPE

Text
T

URI
U

SmartPoster
Sp

ここで指定した内容に応じて、端末で読み取ったときの挙動を制御することができる。

例えばURIであればかざしたときにブラウザが立ち上がるようになる。

RTDの詳細や使用方法は冒頭で紹介した公式スペックを参照してほしい。

本ページではURIを例に挙げる。


NFC URI Record Type Definition

まず、PAYLOAD内はこのようなデータ構造となる。

無題.png

各要素の説明がこちら

要素
説明

Identifier code
URIの識別子コードを指定する。識別子とコードの対応表は別表参照。

URI field
URIをUTF-8で記述する。識別子で指定した分は省略する。

Identifier codeの代表例がこちら。その他のコードはNFC URI Record Type Definition Technical Specificationを参照のこと。

Identifier code
プロトコル

0x00
N/A

0x01

http://www.

0x02

https://www.

0x03
http://

0x04
https://

0x05
tel:

0x06
mailto:

ここで注意すべきことは、このURIのPAYLOADはIdentifier codeで1バイト使用している。

つまり、PAYLOAD LENGTHにはURIフィールドのバイト数+1バイトを指定しなければならない。


NDEFを構築してみる

ここまでの内容を踏まえて、「 http://qiita.com/ 」にアクセスできるNDEFを構築してみる。

無題.png

※タグに書き込む際は終端コードが必須となっている。

この図よりタグに書き込むデータは、

03 0f d1 01

0b 55 03 71

69 69 74 61

2e 63 6f 6d

2f fe

となる。(もしNDEF Recordのみで良い場合は、先頭2バイトと最終1バイトを除けば良い)


参考

避けては通れないバイナリ地獄 - NDEFってなんだろう -