The toolbox for reading and writing nfc cards.
npm install nfccard-toolsh
npm install nfccard-tool --save
`
yarn:
`sh
yarn add nfccard-tool --save
`
Features
* Parse a card header and wrap raw and human readable data in a object:
* Locks states
* Capability Container
* Magic number
* Spec version
* Max NDEF length
* Read and write accesses
* NDEF message detection and length
* Parse and prepare a NDEF message of types:
* Text
* Uri
* Android App Record
Quick start examples (with the help of nfc-pcsc)
$3
`
npm run read-nfcpcsc
`
$3
`
npm run write-nfcpcsc
`
Usage
$3
`js
const ndef = require('nfccard-tool');
`
$3
With the card reader of your choice, read from block 0 until end of block 4. Which means a 20 bytes long read.
> Note: before any NDEF parsing or preparing we need to parse the card header first using a read command.
`js
// Starts reading in block 0 for 20 bytes long
const cardHeader = await reader.read(0, 20);
const tag = nfcCard.parseInfo(cardHeader);
console.log('tag info:', JSON.stringify(tag));
`
Which logs:
`json
tag info:
{
"headerValues":{
"raw":{
"Lock":{
"LOCK0":0,
"LOCK1":0
},
"capabilityContainer":{
"MAGIC_NUMBER":225,
"SPEC_VERSION":16,
"MAX_NDEF_LENGTH":109,
"READ_ACCESS":0,
"WRITE_ACCESS":0
},
"NDEFMessageHeader":{
"HAS_NDEF":3,
"MESSAGE_LENGTH":86
}
},
"string":{
"Lock":{
"LOCK0":"0",
"LOCK1":"0"
},
"capabilityContainer":{
"MAGIC_NUMBER":"E1",
"SPEC_VERSION":"10",
"MAX_NDEF_LENGTH":"6D",
"READ_ACCESS":"0",
"WRITE_ACCESS":"0"
},
"NDEFMessageHeader":{
"HAS_NDEF":"3",
"MESSAGE_LENGTH":"56"
}
}
},
"parsedHeader":{
"isFormatedAsNDEF":true,
"type2SpecVersion":"1.0",
"maxNDEFMessageSize":872,
"hasReadPermissions":true,
"getReadPermissionsType":"HAS_READ_ACCESS",
"hasWritePermissions":true,
"writePermissionsType":"HAS_WRITE_ACCESS",
"hasNDEFMessage":true,
"NDEFMessageLength":86,
"lengthToReadFromBlock4":88
}
}
`
$3
> If card header parsing let us know there might be a NDEF message we can try to parse it:
`js
// There might be a NDEF message and we are able to read the tag
if(nfcCard.isFormatedAsNDEF() && nfcCard.hasReadPermissions() && nfcCard.hasNDEFMessage()) {
// Read the appropriate length to get the NDEF message as buffer
const NDEFRawMessage = await reader.read(4, nfcCard.getNDEFMessageLengthToRead()); // starts reading in block 0 until 6
// Parse the buffer as a NDEF raw message
const NDEFMessage = nfcCard.parseNDEF(NDEFRawMessage);
console.log('NDEFMessage:', NDEFMessage);
} else {
console.log('Could not parse anything from this tag: \n The tag is either empty, locked, has a wrong NDEF format or is unreadable.')
}
`
$3
> We can use the convenient method prepareBytesToWrite to get the appropriate Buffer we need to write a ndef message.
`js
// 1 - READ HEADER
// Starts reading in block 0 until end of block 4
const cardHeader = await reader.read(0, 20);
const tag = nfcCard.parseInfo(cardHeader);
console.log('tag info:', JSON.stringify(tag));
// 2 - WRITE A NDEF MESSAGE AND ITS RECORDS
const message = [
{ type: 'text', text: 'I\'m a text message', language: 'en' },
{ type: 'uri', uri: 'https://github.com/somq' },
{ type: 'aar', packageName: 'https://github.com/somq' },
]
// Prepare the buffer to write on the card
const rawDataToWrite = nfcCard.prepareBytesToWrite(message);
// Write the buffer on the card starting at block 4
const preparationWrite = await reader.write(4, rawDataToWrite.preparedData);
// Success !
if (preparationWrite) {
console.log('Data have been written successfully.')
}
`
Which logs:
`js
NDEFMessage:
[
{ NDEFLibRecord:
{ LanguageCode: null,
text: null,
_typeNameFormat: 1,
_type: [Array],
_id: [],
_payload: [Array] },
type: 'text',
text: 'I\'m a text message',
language: 'en' },
{ NDEFLibRecord:
{ RawUri: [],
Uri: '',
_typeNameFormat: 1,
_type: [Array],
_id: [],
_payload: [Array],
type: 'U' },
type: 'uri',
uri: 'https://github.com/somq' },
{ NDEFLibRecord:
{ packageName: '',
_typeNameFormat: 4,
_type: [Array],
_id: [],
_payload: [Array],
type: 'android.com:pkg' },
type: 'aar',
packageName: 'https://github.com/somq' }
]
`
---
API
$3
`js
// Magic number
nfcCard.isFormatedAsNDEF();
// Type 2 Tag Specification version, eg. 1.0
nfcCard.getType2SpecVersion();
// Max NDEF size for the current tag
nfcCard.getMaxNDEFMessageLength();
// Read locked ?
nfcCard.hasReadPermissions();
// Read types: HAS_READ_ACCESS, RFU, PROPRIETARY, UNKNOWN
nfcCard.getReadPermissionsType();
// Write locked ?
nfcCard.hasWritePermissions();
// Write types: HAS_READ_ACCESS, RFU, PROPRIETARY, UNKNOWN
nfcCard.getWritePermissionsType();
// NDEF message flag is present ?
nfcCard.hasNDEFMessage();
// NDEF message length on exists on the tag
nfcCard.getNDEFMessageLength();
`
$3
`js
{
"headerValues":{
"raw":{ // Raw buffer values
"Lock":{
"LOCK0":0, // Lock 0 status - block 2, byte 2
"LOCK1":0 // Lock 1 status - block 2, byte 3
},
"capabilityContainer":{
"MAGIC_NUMBER":225, // magic number - block 3, byte 0 (CC0)
"SPEC_VERSION":16, // type 2 spec version - block 3, byte 1 (CC1)
"MAX_NDEF_LENGTH":109, // max ndef message length - block 3, byte 2 (CC2)
"READ_ACCESS":0, // read access - block 3, byte 3 (CC3)
"WRITE_ACCESS":0 // write access - block 3, byte 3 (CC3)
},
"NDEFMessageHeader":{
"HAS_NDEF":3, // NDEF header 0 - block 4, byte 0
"MESSAGE_LENGTH":86 // NDEF header 1 - block 4, byte 1
}
},
"string":{ // Hex string values
"Lock":{
"LOCK0":"0",
"LOCK1":"0"
},
"capabilityContainer":{
"MAGIC_NUMBER":"E1",
"SPEC_VERSION":"10",
"MAX_NDEF_LENGTH":"6D",
"READ_ACCESS":"0",
"WRITE_ACCESS":"0"
},
"NDEFMessageHeader":{
"HAS_NDEF":"3",
"MESSAGE_LENGTH":"56"
}
}
},
"parsedHeader":{
"isFormatedAsNDEF":true, // magic number - block 3, byte 0 (CC0)
"type2SpecVersion":"1.0", // type 2 spec version - block 3, byte 1 (CC1)
"maxNDEFMessageSize":872, // max ndef message length - block 3, byte 2
"hasReadPermissions":true, // read access - block 3, byte 3 (CC3)
"getReadPermissionsType":"HAS_READ_ACCESS",
"hasWritePermissions":true, // write access - block 3, byte 3 (CC3)
"writePermissionsType":"HAS_WRITE_ACCESS",
"hasNDEFMessage":true, // NDEF header 0 - block 4, byte 0
"NDEFMessageLength":86, // NDEF header 1 - block 4, byte 1
"lengthToReadFromBlock4":88 // NDEFMessageLength + 2
}
}
`
Compatibility
Only a part of Type 2 tag specification is implemented.
This lib does not support yet:
* Dynamical memory structure
* Lock preparing
... some are probably missing*
Troubleshoot
>Error: path\node_modules\@pokusew\pcsclite\build\Release\ pcsclite.node
`
npm rebuild
``