NFC
Device Compatibility
Overview
The following sections will go over how to install and access the NFC chip on your MATRIX Creator. This library currently implements the following:
- Reading General Information (All tags)
- Reading Pages (MIFARE Ultralight & NTAG)
- Writing to a Page (MIFARE Ultralight & NTAG)
- Reading NDEF (MIFARE Ultralight & NTAG)
- Writing NDEF (MIFARE Ultralight & NTAG)
Helpful Smartphone Apps For NFC:
Installation
Make sure you've installed MATRIX HAL NFC before continuing.
Only one process can interact with the NFC Chip!
This applies to anything that interfaces with NFC, including the C++ library. Multiple processes using NFC will cause unpredictable errors.
Inside your Node.js project, run the following.
npm install @matrix-io/matrix-lite-nfc --save
Import Statement
const nfc = require("@matrix-io/matrix-lite-nfc");
nfc
.status()
When a read or write function completes, it will return a status code to indicate the result. nfc.Status
returns a string of what that number means.
nfc.status(/*number*/); // Example output // nfc.status(256) will return "Activation Done"
.message()
Represents an NDEF message. Each message can contain multiple NDEF Records. Each record can hold text, cellular numbers, emails, links, etc.
// Creates an empty message let msg = new nfc.message(); // Can be initialized from a scanned tag (covered in nfc.read) // let msg = new nfc.message(tag.ndef.content);
.addUriRecord()
msg.addUriRecord("https://community.matrix.one"); msg.addUriRecord("tel:+14085551212"); msg.addUriRecord("sms:+14085551212"); msg.addUriRecord("mailto:user@example.com");
// List of URI protocols // http://www. https://www. http:// https:// tel: mailto: ftp://anonymous:anonymous@ ftp://ftp. ftps:// sftp:// smb:// nfs:// ftp:// dav:// news: telnet:// imap: rtsp:// urn: pop: sip: sips: tftp: btspp:// btl2cap:// btgoep:// tcpobex:// irdaobex:// file:// urn:epc:id: urn:epc:tag: urn:epc:pat: urn:epc:raw: urn:epc: urn:nfc:
.addTextRecord()
// Defaults to en msg.addTextRecord("Hello World"); // Or uses a specified Language msg.addTextRecord("Hola Mundo", "es");
.addMimeMediaRecord()
msg.addMimeMediaRecord("text/json", '{"answer": 42}');
.addEmptyRecord()
msg.addEmptyRecord();
.getRecords()
// Returns an array of objects representing NDEF Records msg.getRecords(); // Example output [ { tnf: 'Well Known', type: 'U', payload: '.https://community.matrix.one', byteSize: 33, typeLength: 1, payloadLength: 29, IdLength: 0 }, { tnf: 'Well Known', type: 'T', payload: '.enHello World', byteSize: 23, typeLength: 1, payloadLength: 19, IdLength: 0 } ]
.getRecord()
// Returns the specified NDEF Record msg.getRecord(0); // Example output { tnf: 'Well Known', type: 'U', payload: '.https://community.matrix.one', byteSize: 33, typeLength: 1, payloadLength: 29, IdLength: 0 }
.getRecordCount()
// Returns the number of NDEF Records in an NDEF Message msg.getRecordCount();
.getEncodedSize()
// Returns the size of the encoded representation of the NDEF message msg.getEncodedSize();
nfc.read
NFC tags are read by using a loop to check if a tag is within range.
.start()
// Configure what you want to read let options = { rate: 100, // Read loop speed (Milliseconds) // At least 1 read options is required. Less options -> faster reading! info: true, // Generic information for any NFC tag pages: true, // All page data page: 0, // A single page(faster than pages) ndef: true // All NDEF data } // Starts the loop nfc.read.start(options, (code, tag) => { // code: NFC activation status // tag : Object with requested NFC data });
.stop()
// Kills the NFC read loop nfc.read.stop();
Reading Examples
const nfc = require("@matrix-io/matrix-lite-nfc"); nfc.read.start({rate:100, info:true}, (code, tag)=>{ if (code === 256){ console.log("Tag Was Scanned"); console.log(tag); } else if (code === 1024) console.log("Nothing Was Scanned"); }); //* Example Output *// { info: { technology: 'A', type: '2', UID: '043F418AA86481', ATQ: '4400', SAK: '00', card_family: 'Mifare Ultralight | NTAG', IC_type: 'NTAG215', bit_rate: -1, storage_size: 504, updated: true, read_status: 0 } }
const nfc = require("@matrix-io/matrix-lite-nfc"); nfc.read.start({rate:100, ndef:true}, (code, tag)=>{ if (code === 256){ console.log("Tag Was Scanned"); // Create an NDEF message from an scanned tag let msg = new nfc.message(tag.ndef.content); console.log(msg.getRecords()); } else if (code === 1024) console.log("Nothing Was Scanned"); }); //* Example Output *// [ { tnf: 'Well Known', type: 'U', payload: '.https://community.matrix.one', byteSize: 33, typeLength: 1, payloadLength: 29, IdLength: 0 }, { tnf: 'Well Known', type: 'T', payload: '.enHello World', byteSize: 23, typeLength: 1, payloadLength: 19, IdLength: 0 } ]
const nfc = require("@matrix-io/matrix-lite-nfc"); nfc.read.start({rate:100, pages:true}, (code, tag)=>{ if (code === 256){ console.log("Tag Was Scanned"); console.log(tag.pages); } else if (code === 1024) console.log("Nothing Was Scanned"); }); //* Example Output *// { read_complete: true, updated: true, content: [ [ 4, 63, 65, 242 ], [ 138, 168, 100, 129 ], [ 199, 72, 0, 0 ], [ 225, 16, 62, 0 ], [ 3, 94, 145, 1 ], [ 29, 85, 0, 104 ], [ 116, 116, 112, 115 ], [ 58, 47, 47, 99 ], [ 111, 109, 109, 117 ], [ 110, 105, 116, 121 ], [ 46, 109, 97, 116 ], [ 114, 105, 120, 46 ], [ 111, 110, 101, 17 ], [ 1, 17, 85, 0 ], [ 116, 101, 108, 58 ], [ 43, 49, 52, 48 ], [ 56, 53, 53, 53 ], [ 49, 50, 49, 50 ], [ 17, 1, 19, 84 ], [ 2, 101, 110, 72 ], [ 101, 108, 108, 111 ], [ 32, 87, 111, 114 ], [ 108, 100, 32, 240 ], [ 159, 153, 130, 81 ], [ 1, 13, 84, 2 ], [ 101, 115, 72, 111 ], [ 108, 97, 32, 77 ], [ 117, 110, 100, 111 ], [ 254, 0, 0, 0 ], [ 254, 0, 0, 0 ], [ 104, 97, 99, 105 ], [ 110, 46, 99, 111 ], [ 109, 254, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], ... 35 more items ], read_status: 17474 }
const nfc = require("@matrix-io/matrix-lite-nfc"); nfc.read.start({rate:100, page:0}, (code, tag)=>{ if (code === 256){ console.log("Tag Was Scanned"); console.log(tag.page); } else if (code === 1024) console.log("Nothing Was Scanned"); }); //* Example Output *// [ 4, 63, 65, 242 ]
const nfc = require("@matrix-io/matrix-lite-nfc"); let options = { rate: 50, // Read loop speed (Milliseconds) // All these options enabled will slow reading speeds info: true, // Generic information for any NFC tag pages: true, // All page data page: 0, // A single page(faster than pages) ndef: true // All NDEF data } // Starts the loop nfc.read.start(options, (code, tag) => { if (code === 256){ console.log("Tag Was Scanned"); console.log(tag); } else if (code === 1024) console.log("Nothing Was Scanned"); }); //* Example Output *// { info: { technology: 'A', type: '2', UID: '043F418AA86481', ATQ: '4400', SAK: '00', card_family: 'Mifare Ultralight | NTAG', IC_type: 'NTAG215', bit_rate: -1, storage_size: 504, updated: true, read_status: 0 }, pages: { read_complete: true, updated: true, content: [ [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], [Array], ... 35 more items ], read_status: 17474 }, page: [ 4, 63, 65, 242 ], ndef: { valid: true, updated: true, content: [ 145, 1, 29, 85, 0, 104, 116, 116, 112, 115, 58, 47, 47, 99, 111, 109, 109, 117, 110, 105, 116, 121, 46, 109, 97, 116, 114, 105, 120, 46, 111, 110, 101, 17, 1, 17, 85, 0, 116, 101, 108, 58, 43, 49, 52, 48, 56, 53, 53, 53, 49, 50, 49, 50, 17, 1, 19, 84, 2, 101, 110, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 32, 240, 159, 153, 130, 81, 1, 13, 84, 2, 101, 115, 72, 111, 108, 97, 32, 77, 117, 110, 100, 111, toString: [Function], toHex: [Function] ], read_status: 0 } }
nfc.write
Writing allows NDEF messages to be written & erased. There is also an option to directly write to a tag's page. Writing is normally done within an NFC read loop.
.message()
// Create an NDEF message with a record var msg = new nfc.message(); msg.addUriRecord("https://community.matrix.one"); // Write the message into the NFC tag nfc.write.message(msg).then((code)=>{ // codes.activation : NFC activation status // codes.write : NFC write status });
.erase()
// Erase the NDEF message on an NFC tag nfc.write.erase().then((code)=>{ // codes.activation : NFC activation status // codes.write : NFC write status });
.page()
Writing to a random page may lock your NFC tag
var page_index = 25; // page you want to overwrite var page_byte = [48,45,59,21]; // Array of numbers that represents a page nfc.write.page(page_index, page_byte).then((code)=>{ // codes.activation : NFC activation status // codes.write : NFC write status });
Writing Examples
const nfc = require("@matrix-io/matrix-lite-nfc"); // Create an NDEF message with a link var msg = new nfc.message(); msg.addUriRecord("https://community.matrix.one"); nfc.read.start({rate: 100, info:true}, (code, tag)=>{ if (code === 256){ nfc.write.message(msg).then((code)=>{ console.log("Activation Status:" + code.activation + " == " + nfc.status(code.activation)); console.log("Write Status:" + code.write + " == " + nfc.status(code.write)); // Exit after successful writing if(code.write === 0) nfc.read.stop(); }); } else if (code === 1024) console.log("Nothing Was Scanned"); });
const nfc = require("@matrix-io/matrix-lite-nfc"); nfc.read.start({rate: 100, info:true}, (code, tag)=>{ if (code === 256){ nfc.write.erase().then((code)=>{ console.log("Activation Status:" + code.activation + " == " + nfc.status(code.activation)); console.log("Write Status:" + code.write + " == " + nfc.status(code.write)); // Exit after successful writing if(code.write === 0) nfc.read.stop(); }); } else if (code === 1024) console.log("Nothing Was Scanned"); });
/* DO NOT WRITE TO A PAGE IF YOU DON'T KNOW WHAT IT DOES. */ const nfc = require("@matrix-io/matrix-lite-nfc"); let page_index = /*insert page number*/; let page_byte = [48,45,59,21]; nfc.read.start({rate: 100, info:true}, (code, tag)=>{ if (code === 256){ nfc.write.page(page_index, page_byte).then((code)=>{ console.log("Activation Status:" + code.activation + " == " + nfc.status(code.activation)); console.log("Write Status:" + code.write + " == " + nfc.status(code.write)); // Exit after successful writing if(code.write === 0) nfc.read.stop(); }); } else if (code === 1024) console.log("Nothing Was Scanned"); });