#include "NdefRecord.h" NdefRecord::NdefRecord() { //Serial.println("NdefRecord Constructor 1"); _tnf = 0; _typeLength = 0; _payloadLength = 0; _idLength = 0; _type = (byte *)NULL; _payload = (byte *)NULL; _id = (byte *)NULL; } NdefRecord::NdefRecord(const NdefRecord& rhs) { //Serial.println("NdefRecord Constructor 2 (copy)"); _tnf = rhs._tnf; _typeLength = rhs._typeLength; _payloadLength = rhs._payloadLength; _idLength = rhs._idLength; _type = (byte *)NULL; _payload = (byte *)NULL; _id = (byte *)NULL; if (_typeLength) { _type = (byte*)malloc(_typeLength); memcpy(_type, rhs._type, _typeLength); } if (_payloadLength) { _payload = (byte*)malloc(_payloadLength); memcpy(_payload, rhs._payload, _payloadLength); } if (_idLength) { _id = (byte*)malloc(_idLength); memcpy(_id, rhs._id, _idLength); } } // TODO NdefRecord::NdefRecord(tnf, type, payload, id) NdefRecord::~NdefRecord() { //Serial.println("NdefRecord Destructor"); if (_typeLength) { free(_type); } if (_payloadLength) { free(_payload); } if (_idLength) { free(_id); } } NdefRecord& NdefRecord::operator=(const NdefRecord& rhs) { //Serial.println("NdefRecord ASSIGN"); if (this != &rhs) { // free existing if (_typeLength) { free(_type); } if (_payloadLength) { free(_payload); } if (_idLength) { free(_id); } _tnf = rhs._tnf; _typeLength = rhs._typeLength; _payloadLength = rhs._payloadLength; _idLength = rhs._idLength; if (_typeLength) { _type = (byte*)malloc(_typeLength); memcpy(_type, rhs._type, _typeLength); } if (_payloadLength) { _payload = (byte*)malloc(_payloadLength); memcpy(_payload, rhs._payload, _payloadLength); } if (_idLength) { _id = (byte*)malloc(_idLength); memcpy(_id, rhs._id, _idLength); } } return *this; } // size of records in bytes int NdefRecord::getEncodedSize() { int size = 2; // tnf + typeLength if (_payloadLength > 0xFF) { size += 4; } else { size += 1; } if (_idLength) { size += 1; } size += (_typeLength + _payloadLength + _idLength); return size; } void NdefRecord::encode(byte *data, bool firstRecord, bool lastRecord) { // assert data > getEncodedSize() uint8_t* data_ptr = &data[0]; *data_ptr = getTnfByte(firstRecord, lastRecord); data_ptr += 1; *data_ptr = _typeLength; data_ptr += 1; if (_payloadLength <= 0xFF) { // short record *data_ptr = _payloadLength; data_ptr += 1; } else { // long format // 4 bytes but we store length as an int data_ptr[0] = 0x0; // (_payloadLength >> 24) & 0xFF; data_ptr[1] = 0x0; // (_payloadLength >> 16) & 0xFF; data_ptr[2] = (_payloadLength >> 8) & 0xFF; data_ptr[3] = _payloadLength & 0xFF; data_ptr += 4; } if (_idLength) { *data_ptr = _idLength; data_ptr += 1; } //Serial.println(2); memcpy(data_ptr, _type, _typeLength); data_ptr += _typeLength; memcpy(data_ptr, _payload, _payloadLength); data_ptr += _payloadLength; if (_idLength) { memcpy(data_ptr, _id, _idLength); data_ptr += _idLength; } } byte NdefRecord::getTnfByte(bool firstRecord, bool lastRecord) { int value = _tnf; if (firstRecord) { // mb value = value | 0x80; } if (lastRecord) { // value = value | 0x40; } // chunked flag is always false for now // if (cf) { // value = value | 0x20; // } if (_payloadLength <= 0xFF) { value = value | 0x10; } if (_idLength) { value = value | 0x8; } return value; } byte NdefRecord::getTnf() { return _tnf; } void NdefRecord::setTnf(byte tnf) { _tnf = tnf; } unsigned int NdefRecord::getTypeLength() { return _typeLength; } int NdefRecord::getPayloadLength() { return _payloadLength; } unsigned int NdefRecord::getIdLength() { return _idLength; } String NdefRecord::getType() { char type[_typeLength + 1]; memcpy(type, _type, _typeLength); type[_typeLength] = '\0'; // null terminate return String(type); } // this assumes the caller created type correctly void NdefRecord::getType(uint8_t* type) { memcpy(type, _type, _typeLength); } void NdefRecord::setType(const byte * type, const unsigned int numBytes) { if(_typeLength) { free(_type); } _type = (uint8_t*)malloc(numBytes); memcpy(_type, type, numBytes); _typeLength = numBytes; } // assumes the caller sized payload properly void NdefRecord::getPayload(byte *payload) { memcpy(payload, _payload, _payloadLength); } void NdefRecord::setPayload(const byte * payload, const int numBytes) { if (_payloadLength) { free(_payload); } _payload = (byte*)malloc(numBytes); memcpy(_payload, payload, numBytes); _payloadLength = numBytes; } String NdefRecord::getId() { char id[_idLength + 1]; memcpy(id, _id, _idLength); id[_idLength] = '\0'; // null terminate return String(id); } void NdefRecord::getId(byte *id) { memcpy(id, _id, _idLength); } void NdefRecord::setId(const byte * id, const unsigned int numBytes) { if (_idLength) { free(_id); } _id = (byte*)malloc(numBytes); memcpy(_id, id, numBytes); _idLength = numBytes; } void NdefRecord::print() { Serial.println(F(" NDEF Record")); Serial.print(F(" TNF 0x"));Serial.print(_tnf, HEX);Serial.print(" "); switch (_tnf) { case TNF_EMPTY: Serial.println(F("Empty")); break; case TNF_WELL_KNOWN: Serial.println(F("Well Known")); break; case TNF_MIME_MEDIA: Serial.println(F("Mime Media")); break; case TNF_ABSOLUTE_URI: Serial.println(F("Absolute URI")); break; case TNF_EXTERNAL_TYPE: Serial.println(F("External")); break; case TNF_UNKNOWN: Serial.println(F("Unknown")); break; case TNF_UNCHANGED: Serial.println(F("Unchanged")); break; case TNF_RESERVED: Serial.println(F("Reserved")); break; default: Serial.println(); } Serial.print(F(" Type Length 0x"));Serial.print(_typeLength, HEX);Serial.print(" ");Serial.println(_typeLength); Serial.print(F(" Payload Length 0x"));Serial.print(_payloadLength, HEX);;Serial.print(" ");Serial.println(_payloadLength); if (_idLength) { Serial.print(F(" Id Length 0x"));Serial.println(_idLength, HEX); } Serial.print(F(" Type "));PrintHexChar(_type, _typeLength); // TODO chunk large payloads so this is readable Serial.print(F(" Payload "));PrintHexChar(_payload, _payloadLength); if (_idLength) { Serial.print(F(" Id "));PrintHexChar(_id, _idLength); } Serial.print(F(" Record is "));Serial.print(getEncodedSize());Serial.println(" bytes"); }