NDEF Creation and Modification Tool¶
The ndeftool is a command line utility for creating, modifying and printing NFC Data Exchange Format (NDEF) Records. It is licensed under the ISCL, hosted on GitHub and installable from PyPI.
$ pip install ndeftool
$ ndeftool --help
NDEFTOOL¶
Create, modify or print NFC Data Exchange Format Records.
Synopsis¶
ndeftool [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Description¶
The ndeftool provides a number of commands to create, modify or print NDEF
records. Commands can be chained together to successively extend or modify the
list of records that are generated. Except for save and print, all
records forwarded by the last command are send to standard output as binary NDEF
message data. The save and print commands implicitly consume all records
unless the --keep
option is set. They also, unlike all other commands, do not
start an empty record list but read from standard input when given as the first
command (the same behavior can be achieved for the load command by setting
the file path to -
).
By default, NDEF records read from disk or standard input must be correctly
formatted NDEF message data (for example, the first and the last record must
have the message begin and end flag set). The --relax
makes the decoder accept
correctable data errors and the --ignore
option will additionally skip records
with uncorrectable errors.
Options¶
-
--version
¶
Show the version and exit.
-
--relax
¶
Ignore some errors when decoding.
-
--ignore
¶
Ignore all errors when decoding.
-
--silent
¶
Suppress all progress information.
-
--debug
¶
Output debug progress information.
-
--help
¶
Show this message and exit.
Commands¶
load¶
Load records or payloads from disk.
Synopsis¶
ndeftool load [OPTIONS] PATH
ndeftool l [OPTIONS] PATH
Description¶
The load command reads records or payloads from disk files or
standard input. The files for reading are determined by the pattern
specified by PATH, which in the simplest form is an existing file
name. Other forms may include *
, ?
and character ranges expressed
by []
. A single -
may be used to read from standard input. Note
that patterns containg wildcards may need to be escaped to avoid shell
expansion.
The default mode of operation is to load files containing NDEF
records. In --pack
mode the files are loaded into the payload of
NDEF records with record type (NDEF Record TNF and TYPE) set to the
mimetype discovered from the payload and record name (NDEF Record ID)
set to the filename.
Options¶
-
-p
,
--pack
¶
Pack files as payload into mimetype records.
-
--help
¶
Show this message and exit.
Examples¶
Pack text from standard input and pack as record.
$ echo -n "Hello World" | ndeftool load --pack - print
NDEF Record TYPE 'text/plain' ID '<stdin>' PAYLOAD 11 byte '48656c6c6f20576f726c' ... 1 more
Read text from file and pack as record.
$ echo -n "Hello World" > /tmp/hello && ndeftool load --pack /tmp/hello print
NDEF Record TYPE 'text/plain' ID '/tmp/hello' PAYLOAD 11 byte '48656c6c6f20576f726c' ... 1 more
Read with path containing wildcard characters.
$ ndeftool load --pack 'i?d*.rst' print
NDEF Record TYPE 'text/plain' ID 'index.rst' PAYLOAD 627 byte '2e2e202d2a2d206d6f64' ... 617 more
Read and pack multiple files.
$ ndeftool load --pack '../se?up.*' print
NDEF Record TYPE 'text/plain' ID '../setup.cfg' PAYLOAD 141 byte '5b746f6f6c3a70797465' ... 131 more
NDEF Record TYPE 'text/x-python' ID '../setup.py' PAYLOAD 2563 byte '23212f7573722f62696e' ... 2553 more
save¶
Save records or payloads to disk.
Synopsis¶
ndeftool save [OPTIONS] PATH
ndeftool s [OPTIONS] PATH
Description¶
The save command writes the current records to disk. The records to write
can be restricted to the subset selected with --skip
, --count
, --head
and
--tail
applied in that order. The default mode is to save all selected records
as one NDEF message into a single file given by PATH. In --burst
mode each
record is written as one NDEF message into a separate file under the directory
given by PATH. The file names are three digit numbers created from the record
index. In --unpack
mode the payload of each record is written to a separate
file under directory PATH with the file name set to the record name (NDEF Record
ID). Records without name are not written unless --unpack
and --burst
are
both set.
The save command does not replace existing files or directories unless this is
requested with --force
.
The save command consumes records from the internal message pipe. This can
be prevented with --keep
, all records are then forwarded to the next command
or written to standard output. When save is the first command it creates the
pipe by reading from standard input.
Options¶
-
--skip
N
¶ Skip the first N records.
-
--count
N
¶ Skip the first N records.
-
--head
N
¶ Save the first N records.
-
--tail
N
¶ Save the last N records.
-
-b
,
--burst
¶
Save single record files in directory.
-
-u
,
--unpack
¶
Unpack records to files in directory.
-
-f
,
--force
¶
Replace existing file or directory.
-
-k
,
--keep
¶
Forward records to next command.
-
--help
¶
Show this message and exit.
Examples¶
Create an NFC Forum Text Record and save it to to a file in the /tmp directory, overwriting the file if it exists.
$ ndeftool text "Hello World" save --force /tmp/hello.ndef
Saving 1 record to /tmp/hello.ndef.
Same as above but the with three NDEF Text Records.
$ ndeftool text One text Two text Three save --force /tmp/text.ndef
Saving 3 records to /tmp/text.ndef.
Out of three records the second is saved using the --skip
and --count
options and the others are forwarded to print.
$ ndeftool txt aa txt bb txt cc save -f --skip 1 --count 1 /tmp/text.ndef print
Saving 1 record to /tmp/text.ndef.
NDEF Text Record ID '' Text 'aa' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID '' Text 'cc' Language 'en' Encoding 'UTF-8'
Out of three records the second is saved using the --head
and --tail
options
and the others are forwarded to print.
$ ndeftool txt aa txt bb txt cc save -f --head 2 --tail 1 /tmp/text.ndef print
Saving 1 record to /tmp/text.ndef.
NDEF Text Record ID '' Text 'aa' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID '' Text 'cc' Language 'en' Encoding 'UTF-8'
Save each record to a separate file with auto-numbered file name plus ndef
extension.
$ ndeftool txt aa txt bb txt cc save -f --burst /tmp/text/
Saving 1 record to /tmp/text/000.ndef.
Saving 1 record to /tmp/text/001.ndef.
Saving 1 record to /tmp/text/002.ndef.
Unpack record payloads to separate files using the record identifier as the file name.
$ ndeftool txt aa id 1.txt txt bb id 2.txt txt cc id 3.txt save -f --unpack /tmp/text/
Saving 1 record to /tmp/text/1.txt.
Saving 1 record to /tmp/text/2.txt.
Saving 1 record to /tmp/text/3.txt.
print¶
Print records as human readable.
Synopsis¶
ndeftool print [OPTIONS]
ndeftool p [OPTIONS]
Description¶
The print command outputs a formatted representation of all current NDEF
Records. By default this is the one line str() representation for each
record. The --long
format produces multiple indented lines per record in an
attempt to provide a more readable output. Printing consumes all records so that
no more data is send to stdout or given to the next command. This can be changed
with the --keep
flag.
When given as the first command print attempts to decode an NDEF message from standard input and process the generated list of records.
Options¶
-
-l
,
--long
¶
Output in a long print format.
-
-k
,
--keep
¶
Keep records for next command.
-
--help
¶
Show this message and exit.
Examples¶
Print records in short format.
$ ndeftool text "Hello World" print
NDEF Text Record ID '' Text 'Hello World' Language 'en' Encoding 'UTF-8'
Print records in long format.
$ ndeftool text "Hello World" print --long
NFC Forum Text Record [record #1]
content Hello World
language en
encoding UTF-8
Print records in both short and long format.
$ ndeftool text "Hello World" print --keep print --long
NDEF Text Record ID '' Text 'Hello World' Language 'en' Encoding 'UTF-8'
NFC Forum Text Record [record #1]
content Hello World
language en
encoding UTF-8
identifier¶
Change the identifier of the last record.
Synopsis¶
ndeftool identifier [OPTIONS] NAME
ndeftool id [OPTIONS] NAME
Description¶
The identifier command either changes the current last record’s name (NDEF Record ID) or, if the current message does not have any records, creates a record with unknown record type and the given record name.
Examples¶
Create a record with unknown
type and set the identifier.
$ ndeftool identifier 'record identifier' print
NDEF Record TYPE 'unknown' ID 'record identifier' PAYLOAD 0 byte
Create two text records with specific identifiers.
$ ndeftool text 'first' id 'r1' text 'second' id 'r2' print
NDEF Text Record ID 'r1' Text 'first' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID 'r2' Text 'second' Language 'en' Encoding 'UTF-8'
typename¶
Change the type name of the last record.
Synopsis¶
ndeftool typename [OPTIONS] TYPE
ndeftool tn [OPTIONS] TYPE
Description¶
The typename command either changes the current last record’s type (NDEF
Record TNF and TYPE) or, if the current message does not have any records,
creates a record with the given record type. The changed record is verified to
successfully encode and decode unless disabled with -x
.
Options¶
-
-x
,
--no-check
¶
Do not check decoding after type name change.
-
--help
¶
Show this message and exit.
Examples¶
Create a record with text/plain
mime type and no payload.
$ ndeftool typename 'text/plain' print
NDEF Record TYPE 'text/plain' ID '' PAYLOAD 0 byte
Create a plain text record and add some payload.
$ ndeftool typename 'text/plain' payload 'Hello World' print
NDEF Record TYPE 'text/plain' ID '' PAYLOAD 11 byte '48656c6c6f20576f726c' ... 1 more
Create a record with a payload that does not match the record type.
$ ndeftool payload 'Hello World' typename -x 'urn:nfc:wkt:T' print -l
Record [record #1]
type urn:nfc:wkt:T
name
data b'Hello World'
payload¶
Change the payload of the last record.
Synopsis¶
ndeftool payload [OPTIONS] DATA
ndeftool pl [OPTIONS] DATA
Description¶
The payload command either changes the current last record’s data (NDEF
Record PAYLOAD) or, if the current message does not have any records, creates a
record with the given record data. The changed record is verified to
successfully encode and decode unless disabled with -x
.
The data string may contain hexadecimal bytes using xNN
notation where
each N is a nibble from [0-F].
Options¶
-
-x
,
--no-check
¶
Do not check decoding after type name change.
-
--help
¶
Show this message and exit.
Examples¶
Create a plain text payload record.
$ ndeftool payload 'Hello World' typename 'text/plain' print
NDEF Record TYPE 'text/plain' ID '' PAYLOAD 11 byte '48656c6c6f20576f726c' ... 1 more
Create an NFC Forum Text record with language code and content.
$ ndeftool payload '\x02enHello World' typename 'urn:nfc:wkt:T' print -l
NFC Forum Text Record [record #1]
content Hello World
language en
encoding UTF-8
Create a record with a payload that does not match the record type. The first command creates an NFC Forum Text Record with language code identifier and text content. The second command then replaces the payload with just the text and would make decoding fail.
$ ndeftool text 'Hello World' payload -x 'Hello World' print -l
Record [record #1]
type urn:nfc:wkt:T
name
data b'Hello World'
text¶
Create an NFC Forum Text Record.
Synopsis¶
ndeftool text [OPTIONS] TEXT
ndeftool txt [OPTIONS] TEXT
Description¶
The text command creates an NFC Forum Text Record with the given input
text. The text language defaults to English (language code en
) and can be set
with --language
followed by the IANA language code. The text content is
encoded as UTF-8 or UTF-16 depending on --encoding
. The default encoding is
UTF-8.
Options¶
-
-l
,
--language
TEXT
¶ Set the IANA language code.
-
--encoding
[UTF-8|UTF-16]
¶ Set the encoding (default UTF-8).
-
--help
¶
Show this message and exit.
Examples¶
Create an NFC Forum Text Record with the default language en
and encoding UTF-8
.
$ ndeftool text 'created with the nfcpy ndeftool' print
NDEF Text Record ID '' Text 'created with the nfcpy ndeftool' Language 'en' Encoding 'UTF-8'
Create one text record with English text and one record with German text.
$ ndeftool text --language en 'English' text --language de 'Deutsch' print
NDEF Text Record ID '' Text 'English' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID '' Text 'Deutsch' Language 'de' Encoding 'UTF-8'
Create a text record with UTF-16 encoding.
$ ndeftool text --encoding UTF-16 'text encoded in UTF-16' | xxd -g 1
00000000: d1 01 31 54 82 65 6e ff fe 74 00 65 00 78 00 74 ..1T.en..t.e.x.t
00000010: 00 20 00 65 00 6e 00 63 00 6f 00 64 00 65 00 64 . .e.n.c.o.d.e.d
00000020: 00 20 00 69 00 6e 00 20 00 55 00 54 00 46 00 2d . .i.n. .U.T.F.-
00000030: 00 31 00 36 00 .1.6.
uri¶
Create an NFC Forum URI Record.
Synopsis¶
ndeftool uri [OPTIONS] RESOURCE
Description¶
The uri command creates an NFC Forum URI Record with the given resource identifier. Note that this is actually an Internationalized Resource Identifier (IRI).
Examples¶
Create a URI record that links to http://nfcpy.org
.
$ ndeftool uri 'http://nfcpy.org' print
NDEF Uri Record ID '' Resource 'http://nfcpy.org'
smartposter¶
Create an NFC Forum Smart Poster Record.
Synopsis¶
ndeftool smartposter [OPTIONS] RESOURCE
ndeftool smp [OPTIONS] RESOURCE
Description¶
The smartposter command creates an NFC Forum Smart Poster Record for the resource identifier. A smart poster record combines the uniform resource identifier with additional data such as titles and icons for representation and processing instructions for the reader application.
A smart poster record should have title text for the desired languages, added
with repetitive -t
options. An English title text may also be added with
-T
. The recommended action set with -a
tells the reader application to
either run the default action for the URI, save it for later or open for
editing.
A smart poster may also provide a collection of icons for graphical
representation. An icon file is added with the -i
option that may be given
more than once. The icon type is determined from the file content and must be an
image or video mime type.
Options¶
-
-T
TEXT
¶ Smartposter title for language code ‘en’.
-
-t
LANG TEXT
¶ Smartposter title for a given language code.
-
-a
[exec|save|edit]
¶ Recommended action for handling the resource.
-
-i
FILENAME
¶ Icon file for a graphical representation.
-
--help
¶
Show this message and exit.
Examples¶
An NFC Forum Smart Poster Record with just a link, nothing more useful than a URI Record.
$ ndeftool smartposter http://nfcpy.org print
NDEF Smartposter Record ID '' Resource 'http://nfcpy.org'
Same as above but with an English title.
$ ndeftool smartposter -T 'nfcpy project' http://nfcpy.org print
NDEF Smartposter Record ID '' Resource 'http://nfcpy.org' Title 'nfcpy project'
Titles for other languages must be given with a language code.
$ ndeftool smartposter -t de 'Google Deutschland' https://www.google.de print
NDEF Smartposter Record ID '' Resource 'https://www.google.de' Title 'Google Deutschland'
An emergency call number should be called immediately.
$ ndeftool smartposter -T 'EMERGENCY CALL 911' -a exec 'tel:911' print -l
NFC Forum Smart Poster Record [record #1]
resource tel:911
action exec
title_en EMERGENCY CALL 911
Add an icon file to a smart poster.
$ ndeftool smp -i images/ndeftool.png https://github.com/nfcpy/ndeftool print -l
NFC Forum Smart Poster Record [record #1]
resource https://github.com/nfcpy/ndeftool
image/png 19941 byte
Examples¶
Any NDEF Record can be constructed with the payload, typename and identifier commands.
$ ndeftool payload '\02ensample text' typename 'urn:nfc:wkt:T' id 'r1' print
NDEF Text Record ID 'r1' Text 'sample text' Language 'en' Encoding 'UTF-8'
The same record can be created with the text command. Here the output goes to stdout and is then printed with a separate ndeftool process call.
$ ndeftool text 'sample text' id 'r1' | ndeftool print
Reading data from standard input
NDEF Text Record ID 'r1' Text 'sample text' Language 'en' Encoding 'UTF-8'
The save command writes the records to disk or <stdout> for path name
-
. The following example creates an NDEF message with three NFC Forum Text
Records, the first and last record with the message begin and message end flags
set.
$ ndeftool text ONE text TWO text THREE save - | xxd -g 1
Saving 3 records to <stdout>.
00000000: 91 01 06 54 02 65 6e 4f 4e 45 11 01 06 54 02 65 ...T.enONE...T.e
00000010: 6e 54 57 4f 51 01 08 54 02 65 6e 54 48 52 45 45 nTWOQ..T.enTHREE
The save command can be used to write intermediate results, here immediately after a text record has been created. Note that by writing to <stdout> the result is a sequence of three individual NDEF messages of one record each. This would not be a proper NDEF message file.
$ ndeftool text ONE save - text TWO save - text THREE save - | xxd -g 1
Saving 1 record to <stdout>.
Saving 1 record to <stdout>.
Saving 1 record to <stdout>.
00000000: d1 01 06 54 02 65 6e 4f 4e 45 d1 01 06 54 02 65 ...T.enONE...T.e
00000010: 6e 54 57 4f d1 01 08 54 02 65 6e 54 48 52 45 45 nTWO...T.enTHREE
The load command reads records from disk or <stdin> for path name -
.
$ ndeftool text ONE text TWO text THREE | ndeftool load - print
loaded 3 record(s) from <stdin>
NDEF Text Record ID '' Text 'ONE' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID '' Text 'TWO' Language 'en' Encoding 'UTF-8'
NDEF Text Record ID '' Text 'THREE' Language 'en' Encoding 'UTF-8'
An empty NDEF Record can be created with an empty type name string. The first
octet 11010000b
sets the Message Begin (MB) and Message End (ME) flags in
the two most signifant bits. The Type Name Format (TNF) value 0 in the least
significant three bits indicates that there is no type or payload associated
with this record and thus the TYPE LENGTH
and PAYLOAD LENGTH
fields must be
zero.
$ ndeftool typename '' | xxd -g 1
00000000: d0 00 00 ...
The default decoding of an NDEF message requires correct data format. Data with
minor format errors can be decoded with the --relax
option. The following
example creates two empty records with invalid MB and ME flags that do only
decode with --relax
.
$ python3 -c "import sys; sys.stdout.buffer.write(b'\x10\0\0\x10\0\0')" | ndeftool --relax print
Reading data from standard input
NDEF Record TYPE '' ID '' PAYLOAD 0 byte
NDEF Record TYPE '' ID '' PAYLOAD 0 byte
NDEF message data with uncorrectable errors can be skipped with the --ignore
option. The payload length 1 in the second record is an invalid value for an
empty record.
$ python3 -c "import sys; sys.stdout.buffer.write(b'\x10\0\0\x10\1\0')" | ndeftool --ignore print
Reading data from standard input
NDEF Record TYPE '' ID '' PAYLOAD 0 byte
Contributing¶
Thank you for considering contributing to ndeftool. There are many ways to help and any help is welcome.
Reporting issues¶
- Under which versions of Python does this happen? This is especially important if your issue is encoding related.
- Under which versions of ndeftool does this happen? Check if this issue is fixed in the repository.
Submitting patches¶
- Include tests if your patch is supposed to solve a bug, and explain clearly under which circumstances the bug happens. Make sure the test fails without your patch.
- Include or update tests and documentation if your patch is supposed to add a new feature. Note that documentation is in two places, the code itself for rendering help pages and in the docs folder for the online documentation.
- Follow PEP 8 and PEP 257.
Development tips¶
Fork the repository and clone it locally:
git clone git@github.com:your-username/ndeftool.git cd ndeftool
Create virtual environments for Python 2 an Python 3, setup the ndeftool package in develop mode, and install required development packages:
virtualenv python-2 python3 -m venv python-3 source python-2/bin/activate python setup.py develop pip install -r requirements-dev.txt source python-3/bin/activate python setup.py develop pip install -r requirements-dev.txt
Verify that all tests pass and the documentation is build:
tox
Preferably develop in the Python 3 virtual environment. Running
tox
ensures tests are run with both the Python 2 and Python 3 interpreter but it takes some time to complete. Alternatively switch back and forth between versions and just run the tests:source python-2/bin/activate py.test source python-3/bin/activate py.test
Test coverage should be close to 100 percent. A great help is the HTML output produced by coverage.py:
py.test --cov ndeftool --cov-report html firefox htmlcov/index.html
The documentation can be created and viewed loacally:
(cd docs && make html) firefox docs/_build/html/index.html
License¶
The ndeftool is licensed under the Internet Systems Consortium ISC license. This is a permissive free software license functionally equivalent to the simplified BSD and the MIT license.
License text¶
ISC License
Copyright (c) 2017 by Stephen Tiedemann.
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.