diff --git a/examples/NDEFSendMessage/NDEFSendMessage.ino b/examples/NDEFSendMessage/NDEFSendMessage.ino index b375692..3300d81 100644 --- a/examples/NDEFSendMessage/NDEFSendMessage.ino +++ b/examples/NDEFSendMessage/NDEFSendMessage.ino @@ -1,10 +1,13 @@ /** * Example to send NDEF messages + * + * Note: If you know how to create custom NDEF messages, you can use the NDEFSendRawMessage example, otherwise, use this example. + * * Authors: * Salvador Mendoza - @Netxing - salmg.net * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -30,10 +33,13 @@ void setup() { ; Serial.println("Send NDEF Message with PN7150"); - message.addTextRecord("Hello"); // English by default - message.addTextRecord("world", "en"); // English explicitly, the library only supports two letter language codes (ISO 639-1) by now - message.addTextRecord("Hola mundo!", "es"); // Spanish explicitly, check a language code table at https://www.science.co.il/language/Locale-codes.php - message.addTextRecord("Bonjour le monde!", "fr"); // French explicitly + message.addTextRecord("Hello"); // English by default + message.addTextRecord("world", "en"); // English explicitly, the library only supports two letter language codes (ISO 639-1) by now + message.addTextRecord("Hola mundo!", "es"); // Spanish explicitly, check a language code table at https://www.science.co.il/language/Locale-codes.php + message.addTextRecord("Bonjour le monde!", "fr"); // French explicitly + message.addUriRecord("google.com"); // No prefix explicitly + message.addUriRecord("https://www.electroniccats.com"); // https://www. prefix explicitly, the library can handle all the prefixes listed at TODO: add link to prefixes table + message.addUriRecord("rtsp://test"); nfc.setSendMsgCallback(messageSentCallback); Serial.println("Initializing..."); diff --git a/examples/NDEFSendRawMessage/NDEFSendRawMessage.ino b/examples/NDEFSendRawMessage/NDEFSendRawMessage.ino index 878eba6..88d5456 100644 --- a/examples/NDEFSendRawMessage/NDEFSendRawMessage.ino +++ b/examples/NDEFSendRawMessage/NDEFSendRawMessage.ino @@ -1,13 +1,13 @@ /** * Example to create a custom NDEF message and send it using the PN7150. - * - * Note: If you know how to create custom NDEF messages, you can use this example, otherwise, use the NDEFSend example. - * + * + * Note: If you know how to create custom NDEF messages, you can use this example, otherwise, use the NDEFSendMessage example. + * * Authors: * Salvador Mendoza - @Netxing - salmg.net * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -28,26 +28,34 @@ Electroniccats_PN7150 nfc(PN7150_IRQ, PN7150_VEN, PN7150_ADDR); // Creates a gl NdefMessage message; // Three records, "Hello", "world" and Uri "https://www.electroniccats.com" -const char ndefMessage[] = {0x91, // MB/ME/CF/1/IL/TNF - 0x01, // Type length (1 byte) - 0x08, // Payload length - 'T', // Type -> 'T' for text, 'U' for URI - 0x02, // Status - 'e', 'n', // Language - 'H', 'e', 'l', 'l', 'o', // Message Payload - 0x11, // MB/ME/CF/1/IL/TNF - 0x01, // Type length (1 byte) - 0x08, // Payload length - 'T', // Type -> 'T' for text, 'U' for URI - 0x02, // Status - 'e', 'n', // Language - 'w', 'o', 'r', 'l', 'd', // Message Payload - 0x51, // MB/ME/CF/1/IL/TNF - 0x01, // Type length (1 byte) - 0x13, // Payload length - 'U', // Type -> 'T' for text, 'U' for URI - 0x02, // Status - 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 'c', 'a', 't', 's', '.', 'c', 'o', 'm'}; // Message Payload +// const char ndefMessage[] = {0x91, // MB/ME/CF/1/IL/TNF +// 0x01, // Type length (1 byte) +// 0x08, // Payload length +// 'T', // Type -> 'T' for text, 'U' for URI +// 0x02, // Status +// 'e', 'n', // Language +// 'H', 'e', 'l', 'l', 'o', // Message Payload +// 0x11, // MB/ME/CF/1/IL/TNF +// 0x01, // Type length (1 byte) +// 0x08, // Payload length +// 'T', // Type -> 'T' for text, 'U' for URI +// 0x02, // Status +// 'e', 'n', // Language +// 'w', 'o', 'r', 'l', 'd', // Message Payload +// 0x51, // MB/ME/CF/1/IL/TNF +// 0x01, // Type length (1 byte) +// 0x13, // Payload length +// 'U', // Type -> 'T' for text, 'U' for URI +// 0x02, // Status +// 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 'c', 'a', 't', 's', '.', 'c', 'o', 'm'}; // Message Payload + +// One uri record "https://www.electroniccats.com" +const char ndefMessage[] = {0xD1, + 0x01, + 0x13, + 'U', + 0x02, + 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 'c', 'a', 't', 's', '.', 'c', 'o', 'm'}; void setup() { Serial.begin(9600); diff --git a/src/NdefMessage.cpp b/src/NdefMessage.cpp index b2fd2ad..37a1ec3 100644 --- a/src/NdefMessage.cpp +++ b/src/NdefMessage.cpp @@ -3,7 +3,7 @@ * Authors: * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -160,14 +160,129 @@ void NdefMessage::addTextRecord(String text, String languageCode) { record.setLanguageCode(languageCode); record.setPayload(text); -#ifdef DEBUG3 - Serial.println("Payload size: " + String(record.getPayloadSize())); - Serial.println("Payload: " + String((char *)record.getPayload())); -#endif - addRecord(record); } void NdefMessage::addTextRecord(String text) { addTextRecord(text, NDEF_DEFAULT_LANGUAGE_CODE); } + +void NdefMessage::addUriRecord(String uri) { + NdefRecord record; + record.setHeaderFlags(NDEF_HEADER_FLAGS_SINGLE_RECORD); + record.setTypeLength(NDEF_TYPE_LENGTH); + record.setPayloadSize(uri.length() + 3); + record.setRecordType(NDEF_URI_RECORD_TYPE); + + if (uri.startsWith("http://www.")) { + record.setStatus(NDEF_URI_HTTP_WWWDOT); + record.setPayload(uri.substring(11).c_str()); + } else if (uri.startsWith("https://www.")) { + record.setStatus(NDEF_URI_HTTPS_WWWDOT); + record.setPayload(uri.substring(12).c_str()); + } else if (uri.startsWith("http://")) { + record.setStatus(NDEF_URI_HTTP); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("https://")) { + record.setStatus(NDEF_URI_HTTPS); + record.setPayload(uri.substring(8).c_str()); + } else if (uri.startsWith("tel:")) { + record.setStatus(NDEF_URI_TEL); + record.setPayload(uri.substring(4).c_str()); + } else if (uri.startsWith("mailto:")) { + record.setStatus(NDEF_URI_MAILTO); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("ftp://anonymous:anonymous@")) { + record.setStatus(NDEF_URI_FTP_ANONIMOUS); + record.setPayload(uri.substring(26).c_str()); + } else if (uri.startsWith("ftp://ftp.")) { + record.setStatus(NDEF_URI_FTP_FTPDOT); + record.setPayload(uri.substring(9).c_str()); + } else if (uri.startsWith("ftps://")) { + record.setStatus(NDEF_URI_FTPS); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("sftp://")) { + record.setStatus(NDEF_URI_SFTP); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("smb://")) { + record.setStatus(NDEF_URI_SMB); + record.setPayload(uri.substring(6).c_str()); + } else if (uri.startsWith("nfs://")) { + record.setStatus(NDEF_URI_NFS); + record.setPayload(uri.substring(6).c_str()); + } else if (uri.startsWith("ftp://")) { + record.setStatus(NDEF_URI_FTP); + record.setPayload(uri.substring(6).c_str()); + } else if (uri.startsWith("dav://")) { + record.setStatus(NDEF_URI_DAV); + record.setPayload(uri.substring(6).c_str()); + } else if (uri.startsWith("news:")) { + record.setStatus(NDEF_URI_NEWS); + record.setPayload(uri.substring(5).c_str()); + } else if (uri.startsWith("telnet://")) { + record.setStatus(NDEF_URI_TELNET); + record.setPayload(uri.substring(9).c_str()); + } else if (uri.startsWith("imap:")) { + record.setStatus(NDEF_URI_IMAP); + record.setPayload(uri.substring(5).c_str()); + } else if (uri.startsWith("rtsp://")) { + record.setStatus(NDEF_URI_RTSP); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("urn:")) { + record.setStatus(NDEF_URI_URN); + record.setPayload(uri.substring(4).c_str()); + } else if (uri.startsWith("pop:")) { + record.setStatus(NDEF_URI_POP); + record.setPayload(uri.substring(4).c_str()); + } else if (uri.startsWith("sip:")) { + record.setStatus(NDEF_URI_SIP); + record.setPayload(uri.substring(4).c_str()); + } else if (uri.startsWith("sips:")) { + record.setStatus(NDEF_URI_SIPS); + record.setPayload(uri.substring(5).c_str()); + } else if (uri.startsWith("tftp:")) { + record.setStatus(NDEF_URI_TFTP); + record.setPayload(uri.substring(5).c_str()); + } else if (uri.startsWith("btspp://")) { + record.setStatus(NDEF_URI_BTSPP); + record.setPayload(uri.substring(8).c_str()); + } else if (uri.startsWith("btl2cap://")) { + record.setStatus(NDEF_URI_BTL2CAP); + record.setPayload(uri.substring(10).c_str()); + } else if (uri.startsWith("btgoep://")) { + record.setStatus(NDEF_URI_BTGOEP); + record.setPayload(uri.substring(9).c_str()); + } else if (uri.startsWith("tcpobex://")) { + record.setStatus(NDEF_URI_TCPOBEX); + record.setPayload(uri.substring(10).c_str()); + } else if (uri.startsWith("irdaobex://")) { + record.setStatus(NDEF_URI_IRDAOBEX); + record.setPayload(uri.substring(11).c_str()); + } else if (uri.startsWith("file://")) { + record.setStatus(NDEF_URI_FILE); + record.setPayload(uri.substring(7).c_str()); + } else if (uri.startsWith("urn:epc:id:")) { + record.setStatus(NDEF_URI_URN_EPC_ID); + record.setPayload(uri.substring(11).c_str()); + } else if (uri.startsWith("urn:epc:tag:")) { + record.setStatus(NDEF_URI_URN_EPC_TAG); + record.setPayload(uri.substring(12).c_str()); + } else if (uri.startsWith("urn:epc:pat:")) { + record.setStatus(NDEF_URI_URN_EPC_PAT); + record.setPayload(uri.substring(12).c_str()); + } else if (uri.startsWith("urn:epc:raw:")) { + record.setStatus(NDEF_URI_URN_EPC_RAW); + record.setPayload(uri.substring(12).c_str()); + } else if (uri.startsWith("urn:epc:")) { + record.setStatus(NDEF_URI_URN_EPC); + record.setPayload(uri.substring(8).c_str()); + } else if (uri.startsWith("urn:nfc:")) { + record.setStatus(NDEF_URI_URN_NFC); + record.setPayload(uri.substring(8).c_str()); + } else { + record.setStatus(NDEF_URI_NO_PREFIX); + record.setPayload(uri); + } + + addRecord(record); +} diff --git a/src/NdefMessage.h b/src/NdefMessage.h index 91124a7..116f300 100644 --- a/src/NdefMessage.h +++ b/src/NdefMessage.h @@ -3,7 +3,7 @@ * Authors: * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -21,7 +21,6 @@ #include "T4T_NDEF_emu.h" #include "ndef_helper.h" -#define MAX_NDEF_RECORDS 4 #define NDEF_HEADER_FLAGS_SINGLE_RECORD 0xD1 #define NDEF_HEADER_FLAGS_FIRST_RECORD 0x91 #define NDEF_HEADER_FLAGS_NEXT_RECORD 0x11 @@ -32,9 +31,45 @@ #define NDEF_STATUS 0x02 #define NDEF_DEFAULT_LANGUAGE_CODE "en" -class NdefMessage : NdefRecord { +#define NDEF_URI_NO_PREFIX 0x00 +#define NDEF_URI_HTTP_WWWDOT 0x01 +#define NDEF_URI_HTTPS_WWWDOT 0x02 +#define NDEF_URI_HTTP 0x03 +#define NDEF_URI_HTTPS 0x04 +#define NDEF_URI_TEL 0x05 +#define NDEF_URI_MAILTO 0x06 +#define NDEF_URI_FTP_ANONIMOUS 0x07 +#define NDEF_URI_FTP_FTPDOT 0x08 +#define NDEF_URI_FTPS 0x09 +#define NDEF_URI_SFTP 0x0A +#define NDEF_URI_SMB 0x0B +#define NDEF_URI_NFS 0x0C +#define NDEF_URI_FTP 0x0D +#define NDEF_URI_DAV 0x0E +#define NDEF_URI_NEWS 0x0F +#define NDEF_URI_TELNET 0x10 +#define NDEF_URI_IMAP 0x11 +#define NDEF_URI_RTSP 0x12 +#define NDEF_URI_URN 0x13 +#define NDEF_URI_POP 0x14 +#define NDEF_URI_SIP 0x15 +#define NDEF_URI_SIPS 0x16 +#define NDEF_URI_TFTP 0x17 +#define NDEF_URI_BTSPP 0x18 +#define NDEF_URI_BTL2CAP 0x19 +#define NDEF_URI_BTGOEP 0x1A +#define NDEF_URI_TCPOBEX 0x1B +#define NDEF_URI_IRDAOBEX 0x1C +#define NDEF_URI_FILE 0x1D +#define NDEF_URI_URN_EPC_ID 0x1E +#define NDEF_URI_URN_EPC_TAG 0x1F +#define NDEF_URI_URN_EPC_PAT 0x20 +#define NDEF_URI_URN_EPC_RAW 0x21 +#define NDEF_URI_URN_EPC 0x22 +#define NDEF_URI_URN_NFC 0x23 + +class NdefMessage { private: - NdefRecord records[MAX_NDEF_RECORDS]; static uint8_t recordCounter; static unsigned char *content; static unsigned short contentSize; @@ -44,7 +79,6 @@ class NdefMessage : NdefRecord { void getNextRecord(); static String getHexRepresentation(const byte *data, const uint32_t dataSize); static String newString; - static void addContent(const char *record, unsigned short recordSize); void addRecord(NdefRecord record); static void updateHeaderFlags(); diff --git a/src/NdefRecord.cpp b/src/NdefRecord.cpp index fd17ba6..ffbe993 100644 --- a/src/NdefRecord.cpp +++ b/src/NdefRecord.cpp @@ -3,7 +3,7 @@ * Authors: * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -23,6 +23,11 @@ NdefRecord::NdefRecord() { this->status = 0; this->languageCode = 0; this->newString = "null"; + this->textRecord = false; +} + +bool NdefRecord::isTextRecord() { + return this->textRecord; } void NdefRecord::create(NdefRecord_t record) { @@ -240,6 +245,9 @@ String NdefRecord::getUri() { } void NdefRecord::setPayload(String payload) { +#ifdef DEBUG3 + Serial.println("Payload: " + payload); +#endif this->payload = new unsigned char[payload.length()]; strcpy((char *)this->payload, payload.c_str()); } @@ -261,6 +269,7 @@ void NdefRecord::setStatus(uint8_t status) { } void NdefRecord::setLanguageCode(String languageCode) { + this->textRecord = true; this->languageCode = new unsigned char[languageCode.length()]; strcpy((char *)this->languageCode, languageCode.c_str()); } @@ -277,16 +286,23 @@ const char *NdefRecord::getContent() { recordContent[2] = payloadSize; recordContent[3] = recordType; recordContent[4] = status; - recordContent[5] = languageCode[0]; - recordContent[6] = languageCode[1]; - for (int i = 0; i < getPayloadSize(); i++) { - recordContent[i + 7] = payload[i]; + if (isTextRecord()) { + recordContent[5] = languageCode[0]; + recordContent[6] = languageCode[1]; + + for (int i = 0; i < getPayloadSize(); i++) { + recordContent[i + 7] = payload[i]; + } + } else { + for (int i = 0; i < getPayloadSize(); i++) { + recordContent[i + 5] = payload[i]; + } } return recordContent; } unsigned short NdefRecord::getContentSize() { - return getPayloadSize() + 4; // 4 bytes for header, type length, payload length and record type + return getPayloadSize() + 4; // 4 bytes for header, type length, payload length and record type } diff --git a/src/NdefRecord.h b/src/NdefRecord.h index 0e9236f..8c660d9 100644 --- a/src/NdefRecord.h +++ b/src/NdefRecord.h @@ -3,7 +3,7 @@ * Authors: * Francisco Torres - Electronic Cats - electroniccats.com * - * August 2023 + * December 2023 * * This code is beerware; if you see me (or any other collaborator * member) at the local, and you've found our code helpful, @@ -35,8 +35,10 @@ class NdefRecord { uint8_t status; unsigned char *languageCode; unsigned char *payload; - String getHexRepresentation(const byte *data, const uint32_t dataSize); String newString; + bool textRecord; + String getHexRepresentation(const byte *data, const uint32_t dataSize); + bool isTextRecord(); public: NdefRecord();