Запись данных NDEF в тег NTAG216 с использованием низкоуровневых методов связи NFC

Я реализовал код для взаимодействия с NTAG216 с помощью низкоуровневых методов связи (следуя NTAG212 Mifare Ultralight with Authentication и техпаспорт NTAG216).

Что я достиг до сих пор:

  • Установите защиту от записи паролем на NTAG216, если он не установлен или если тег новый/пустой.
  • Если пароль уже установлен, выполните аутентификацию, используя PWD_AUTH и сравнивая PACK.
  • Прочитать данные.
  • Запись/перезапись данных.

То, что я не смог сделать до сих пор:

  • Обнаружение сообщений NDEF, которые я пишу в тег в других приложениях. Другими словами, я могу писать в тег, используя метод writePage(), а также читать теги, используя readPage(). Однако во время написания страниц я преобразовываю NdefMessage в массив байтов, который можно читать и записывать. Однако это сообщение NDEF не обнаруживается в других приложениях.

Что мне нужно сделать, чтобы иметь возможность обнаруживать сообщения NDEF, которые я пишу из других приложений?


person phLamBy    schedule 08.02.2017    source источник


Ответы (1)


NTAG216 — это метка NFC Forum Type 2. Следовательно, вы должны следовать форуму NFC Теговая операция типа 2. спецификация при записи данных в этот тип метки NFC.

Поэтому вам нужно будет следовать нескольким правилам, чтобы тег можно было обнаружить как тег NDEF (тег типа 2):

Во-первых, необходимо настроить контейнер возможностей (расположенный в блоке 3).

  • Байт 0 должен быть установлен в «магическое» значение 0xE1.
  • Байт 1 должен быть установлен на 0x10, чтобы указать версию отображения 1.0.
  • Байт 2 должен быть установлен на 0x6D, чтобы указать размер памяти NTAG216.
  • Байт 3 может быть установлен на 0x00, чтобы указать доступ для чтения/записи к данным NDEF, или на 0x0F, чтобы указать доступ только для чтения (обратите внимание, что это разрешения на прикладном уровне).

Таким образом, вы можете написать контейнер возможностей как:

byte[] response = nfc.transceive(new byte[] {
    (byte)0xA2, // WRITE
    (byte)3,    // block address
    (byte)0xE1, (byte)0x10, (byte)0x6D, (byte)0x00
});

NTAG216 уже поставляется с правильно настроенным контейнером возможностей, поэтому нет необходимости делать это вручную. Также обратите внимание, что блок 3 программируется один раз, что означает, что биты могут быть установлены только на единицу, но не могут быть снова очищены до нуля. Поэтому, если вы уже перезаписали контейнер возможностей другим значением, этот тег, скорее всего, больше нельзя будет использовать в качестве тега NDEF.

Данные должны быть записаны в блоки данных, начиная с блока 4. Сообщения NDEF должны быть заключены в структуру сообщения NDEF TLV (значение длины тега). Тег для этого TLV — 0x03. Длина может быть либо в однобайтовом формате (для сообщений NDEF длиной от 0 до 254 байтов), либо в трехбайтовом формате (для сообщений NDEF длиной 255 и более байтов). Данные этого блока TLV являются фактическим сообщением NDEF (которое вы можете получить от ndefMessage.toByteArray()).

Например, для сообщения NDEF D1 01 0C 55 01 65 78 61 6D 70 6C 65 2E 63 6F 6D 2F (которое представляет собой запись URI с URL-адресом "http://www.example.com/"), вы получите следующую структуру TLV:

03 11 D1010C55016578616D706C652E636F6D2F

Если у вас есть более длинное сообщение NDEF (например, с 259 байтами), вы должны использовать трехбайтовый формат длины:

03 FF0103 D101FF5501...

Далее следует пометить конец данных в теге с помощью Terminator TLV (тег 0xFE, без полей длины и данных):

FE

Затем вы можете записать эти данные в тег как:

byte[] ndefMessage = new byte[] {
    (byte)0xD1, (byte)0x01, (byte)0x0C, (byte)0x55, (byte)0x01, (byte)0x65, (byte)0x78, (byte)0x61, (byte)0x6D, (byte)0x70, (byte)0x6C, (byte)0x65, (byte)0x2E, (byte)0x63, (byte)0x6F, (byte)0x6D, (byte)0x2F
};

// wrap into TLV structure
byte[] tlvEncodedData = null;
if (ndefMessage.length < 255) {
    tlvEncodedData = new byte[ndefMessage.length + 3];
    tlvEncodedData[0] = (byte)0x03;  // NDEF TLV tag
    tlvEncodedData[1] = (byte)(ndefMessage.length & 0x0FF);  // NDEF TLV length (1 byte)
    System.arraycopy(ndefMessage, 0, tlvEncodedData, 2, ndefMessage.length);
    tlvEncodedData[2 + ndefMessage.length] = (byte)0xFE;  // Terminator TLV tag
} else {
    tlvEncodedData = new byte[ndefMessage.length + 5];
    tlvEncodedData[0] = (byte)0x03;  // NDEF TLV tag
    tlvEncodedData[1] = (byte)0xFF;  // NDEF TLV length (3 byte, marker)
    tlvEncodedData[2] = (byte)((ndefMessage.length >>> 8) & 0x0FF);  // NDEF TLV length (3 byte, hi)
    tlvEncodedData[3] = (byte)(ndefMessage.length & 0x0FF);          // NDEF TLV length (3 byte, lo)
    System.arraycopy(ndefMessage, 0, tlvEncodedData, 4, ndefMessage.length);
    tlvEncodedData[4 + ndefMessage.length] = (byte)0xFE;  // Terminator TLV tag
}

// fill up with zeros to block boundary:
tlvEncodedData = Arrays.copyOf(tlvEncodedData, (tlvEncodedData.length / 4 + 1) * 4);
for (int i = 0; i < tlvEncodedData.length; i += 4) {
    byte[] command = new byte[] {
        (byte)0xA2, // WRITE
        (byte)((4 + i / 4) & 0x0FF), // block address
        0, 0, 0, 0
    };
    System.arraycopy(tlvEncodedData, i, command, 2, 4);
    byte[] response = nfc.transceive(command);
}

Наконец, имейте в виду, что вы не можете использовать тег в качестве тега NDEF, если у вас установлен пароль для чтения в области данных NDEF, поскольку спецификация NFC Forum Type 2 Tag Operation требует, чтобы тег был свободно читаемым.

person Michael Roland    schedule 08.02.2017
comment
Я в командировке до конца февраля. Как только я вернусь к работе, я реализую и протестирую его, я приму ваш ответ. Но теоретически вы решили мою проблему. Спасибо. - person phLamBy; 10.02.2017
comment
Спасибо за терпение и усилия, чтобы ответить на мой вопрос. Я интегрировал ваш код с моим. 1) Сначала я аутентифицировал карту 2) написал контейнер возможностей, а затем записал свои данные, используя данный код. Но все же я не могу обнаружить тег Ndef в других приложениях. мой NdefMessage содержит два тега. Первый — это MIME (имя пакета приложения), второй — текстовая запись (JSON MESSAGE). - person phLamBy; 08.03.2017
comment
Part1: -110 34 0 97 112 112 108 105 99 97 112 108 105 99 97 116 105 111 110 47 111 114 103 46 111 99 46 111 115 111 46 110 102 99 97 99 116 105 118 105 116 121 81 1 -58 84 2 101 110 47 82 75 103 69 111 80 81 43 104 111 70 70 119 99 74 108 43 82 43 75 84 52 53 98 43 75 84 52 53 98 121 118 55 48 48 69 89 108 56 110 107 87 102 107 48 67 89 56 83 53 86 55 110 99 65 80 89 107 105 51 74 117 101 55 48 73 110 97 47 83 113 105 104 101 53 87 67 52 78 83 43 10 72 75 55 53 77 47 77 120 80 83 78 112 121 105 78 121 71 121 69 103 80 106 56 54 52 52 74 87 87 78 70 88 85 72 82 83 115 54 78 79 78 53 115 109 66 79 106 67 53 90 78 73 80 107 71 108 - person phLamBy; 08.03.2017
comment
Part2: 119 97 54 106 43 111 53 65 57 88 120 89 120 86 112 51 51 113 52 70 68 10 66 53 88 106 76 105 109 112 116 56 71 97 99 85 101 89 82 51 65 114 82 79 67 90 76 82 103 56 77 100 48 98 72 68 88 114 72 121 71 72 10 Это сообщение NdefMessage, которое я использовал. - person phLamBy; 08.03.2017
comment
@KailashKumar Вы правильно обернули сообщение NDEF в структуру TLV? Вы записали данные в правильные блоки? - person Michael Roland; 11.03.2017
comment
Я точно следовал вашему коду, так как данные меньше 255 байт, после записи данных я нашел CC как FF FF FF FF, перед записью он показал E1 10 6D 00, и теперь я даже не могу записать CC, как это было раньше. - person phLamBy; 14.03.2017
comment
@KailashKumar Мне очень жаль. К сожалению, у меня действительно была ошибка в коде, из-за которой все данные записывались в блок CC. Это, в свою очередь, привело к тому, что блок CC стал FF FF FF FF (что означает, что тег больше нельзя использовать для NDEF; к сожалению, это состояние необратимо). Я обновил код, чтобы правильно увеличить счетчик блоков. - person Michael Roland; 14.03.2017
comment
Я уже определил и исправил эту ошибку, но ваш код лучше моего, поэтому я использовал ваш код. а также потратил впустую 4 карты NFC из-за этой ошибки .. :). Во всяком случае, это решило мою проблему. Спасибо за ваше время (Y) - person phLamBy; 14.03.2017