mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-15 11:19:33 +01:00
275 lines
6.0 KiB
C++
275 lines
6.0 KiB
C++
#include <NdefMessage.h>
|
|
|
|
NdefMessage::NdefMessage(void)
|
|
{
|
|
_recordCount = 0;
|
|
}
|
|
|
|
NdefMessage::NdefMessage(const byte * data, const int numBytes)
|
|
{
|
|
#ifdef NDEF_DEBUG
|
|
Serial.print(F("Decoding "));Serial.print(numBytes);Serial.println(F(" bytes"));
|
|
PrintHexChar(data, numBytes);
|
|
//DumpHex(data, numBytes, 16);
|
|
#endif
|
|
|
|
_recordCount = 0;
|
|
|
|
int index = 0;
|
|
|
|
while (index <= numBytes)
|
|
{
|
|
|
|
// decode tnf - first byte is tnf with bit flags
|
|
// see the NFDEF spec for more info
|
|
byte tnf_byte = data[index];
|
|
bool mb = (tnf_byte & 0x80) != 0;
|
|
bool me = (tnf_byte & 0x40) != 0;
|
|
bool cf = (tnf_byte & 0x20) != 0;
|
|
bool sr = (tnf_byte & 0x10) != 0;
|
|
bool il = (tnf_byte & 0x8) != 0;
|
|
byte tnf = (tnf_byte & 0x7);
|
|
|
|
NdefRecord record = NdefRecord();
|
|
record.setTnf(tnf);
|
|
|
|
index++;
|
|
int typeLength = data[index];
|
|
|
|
int payloadLength = 0;
|
|
if (sr)
|
|
{
|
|
index++;
|
|
payloadLength = data[index];
|
|
}
|
|
else
|
|
{
|
|
payloadLength =
|
|
((0xFF & data[++index]) << 24)
|
|
| ((0xFF & data[++index]) << 16)
|
|
| ((0xFF & data[++index]) << 8)
|
|
| (0xFF & data[++index]);
|
|
}
|
|
|
|
int idLength = 0;
|
|
if (il)
|
|
{
|
|
index++;
|
|
idLength = data[index];
|
|
}
|
|
|
|
index++;
|
|
record.setType(&data[index], typeLength);
|
|
index += typeLength;
|
|
|
|
if (il)
|
|
{
|
|
record.setId(&data[index], idLength);
|
|
index += idLength;
|
|
}
|
|
|
|
record.setPayload(&data[index], payloadLength);
|
|
index += payloadLength;
|
|
|
|
addRecord(record);
|
|
|
|
if (me) break; // last message
|
|
}
|
|
|
|
}
|
|
|
|
NdefMessage::NdefMessage(const NdefMessage& rhs)
|
|
{
|
|
|
|
_recordCount = rhs._recordCount;
|
|
for (int i = 0; i < _recordCount; i++)
|
|
{
|
|
_records[i] = rhs._records[i];
|
|
}
|
|
|
|
}
|
|
|
|
NdefMessage::~NdefMessage()
|
|
{
|
|
}
|
|
|
|
NdefMessage& NdefMessage::operator=(const NdefMessage& rhs)
|
|
{
|
|
|
|
if (this != &rhs)
|
|
{
|
|
|
|
// delete existing records
|
|
for (int i = 0; i < _recordCount; i++)
|
|
{
|
|
// TODO Dave: is this the right way to delete existing records?
|
|
_records[i] = NdefRecord();
|
|
}
|
|
|
|
_recordCount = rhs._recordCount;
|
|
for (int i = 0; i < _recordCount; i++)
|
|
{
|
|
_records[i] = rhs._records[i];
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
unsigned int NdefMessage::getRecordCount()
|
|
{
|
|
return _recordCount;
|
|
}
|
|
|
|
int NdefMessage::getEncodedSize()
|
|
{
|
|
int size = 0;
|
|
for (int i = 0; i < _recordCount; i++)
|
|
{
|
|
size += _records[i].getEncodedSize();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
// TODO change this to return uint8_t*
|
|
void NdefMessage::encode(uint8_t* data)
|
|
{
|
|
// assert sizeof(data) >= getEncodedSize()
|
|
uint8_t* data_ptr = &data[0];
|
|
|
|
for (int i = 0; i < _recordCount; i++)
|
|
{
|
|
_records[i].encode(data_ptr, i == 0, (i + 1) == _recordCount);
|
|
// TODO can NdefRecord.encode return the record size?
|
|
data_ptr += _records[i].getEncodedSize();
|
|
}
|
|
|
|
}
|
|
|
|
boolean NdefMessage::addRecord(NdefRecord& record)
|
|
{
|
|
|
|
if (_recordCount < MAX_NDEF_RECORDS)
|
|
{
|
|
_records[_recordCount] = record;
|
|
_recordCount++;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
Serial.println(F("WARNING: Too many records. Increase MAX_NDEF_RECORDS."));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void NdefMessage::addMimeMediaRecord(String mimeType, String payload)
|
|
{
|
|
|
|
byte payloadBytes[payload.length() + 1];
|
|
payload.getBytes(payloadBytes, sizeof(payloadBytes));
|
|
|
|
addMimeMediaRecord(mimeType, payloadBytes, payload.length());
|
|
}
|
|
|
|
void NdefMessage::addMimeMediaRecord(String mimeType, uint8_t* payload, int payloadLength)
|
|
{
|
|
NdefRecord r = NdefRecord();
|
|
r.setTnf(TNF_MIME_MEDIA);
|
|
|
|
byte type[mimeType.length() + 1];
|
|
mimeType.getBytes(type, sizeof(type));
|
|
r.setType(type, mimeType.length());
|
|
|
|
r.setPayload(payload, payloadLength);
|
|
|
|
addRecord(r);
|
|
}
|
|
|
|
void NdefMessage::addTextRecord(String text)
|
|
{
|
|
addTextRecord(text, "en");
|
|
}
|
|
|
|
void NdefMessage::addTextRecord(String text, String encoding)
|
|
{
|
|
NdefRecord r = NdefRecord();
|
|
r.setTnf(TNF_WELL_KNOWN);
|
|
|
|
uint8_t RTD_TEXT[1] = { 0x54 }; // TODO this should be a constant or preprocessor
|
|
r.setType(RTD_TEXT, sizeof(RTD_TEXT));
|
|
|
|
// X is a placeholder for encoding length
|
|
// TODO is it more efficient to build w/o string concatenation?
|
|
String payloadString = "X" + encoding + text;
|
|
|
|
byte payload[payloadString.length() + 1];
|
|
payloadString.getBytes(payload, sizeof(payload));
|
|
|
|
// replace X with the real encoding length
|
|
payload[0] = encoding.length();
|
|
|
|
r.setPayload(payload, payloadString.length());
|
|
|
|
addRecord(r);
|
|
}
|
|
|
|
void NdefMessage::addUriRecord(String uri)
|
|
{
|
|
NdefRecord* r = new NdefRecord();
|
|
r->setTnf(TNF_WELL_KNOWN);
|
|
|
|
uint8_t RTD_URI[1] = { 0x55 }; // TODO this should be a constant or preprocessor
|
|
r->setType(RTD_URI, sizeof(RTD_URI));
|
|
|
|
// X is a placeholder for identifier code
|
|
String payloadString = "X" + uri;
|
|
|
|
byte payload[payloadString.length() + 1];
|
|
payloadString.getBytes(payload, sizeof(payload));
|
|
|
|
// add identifier code 0x0, meaning no prefix substitution
|
|
payload[0] = 0x0;
|
|
|
|
r->setPayload(payload, payloadString.length());
|
|
|
|
addRecord(*r);
|
|
delete(r);
|
|
}
|
|
|
|
void NdefMessage::addEmptyRecord()
|
|
{
|
|
NdefRecord* r = new NdefRecord();
|
|
r->setTnf(TNF_EMPTY);
|
|
addRecord(*r);
|
|
delete(r);
|
|
}
|
|
|
|
NdefRecord NdefMessage::getRecord(int index)
|
|
{
|
|
if (index > -1 && index < _recordCount)
|
|
{
|
|
return _records[index];
|
|
}
|
|
else
|
|
{
|
|
return NdefRecord(); // would rather return NULL
|
|
}
|
|
}
|
|
|
|
NdefRecord NdefMessage::operator[](int index)
|
|
{
|
|
return getRecord(index);
|
|
}
|
|
|
|
void NdefMessage::print()
|
|
{
|
|
Serial.print(F("\nNDEF Message "));Serial.print(_recordCount);Serial.print(F(" record"));
|
|
_recordCount == 1 ? Serial.print(", ") : Serial.print("s, ");
|
|
Serial.print(getEncodedSize());Serial.println(F(" bytes"));
|
|
|
|
int i;
|
|
for (i = 0; i < _recordCount; i++)
|
|
{
|
|
_records[i].print();
|
|
}
|
|
}
|