Skip to content

RFID Протокол записи

Концепция

Backend формирует готовый бинарный blob, MCU записывает на метку по универсальному алгоритму.

Архитектура

Уровень A: Содержимое blob

Backend выбирает формат по технологии: - NDEF Type 2 (NTAG/Ultralight) - TLV с page 4 - NDEF Type 5 (ISO15693) - CC в block 0 - Vendor-format (MIFARE Classic)

Уровень B: Параметры записи

Backend передает инструкции: - tech: тип технологии - chunkSize: размер записи (4/8/16 байт) - startAddr: стартовый адрес - needsAuth: требуется аутентификация - auth: ключи (только для MIFARE Classic)

Технологии

Параметр Type 2 (NTAG) MIFARE Classic ISO15693
Чанк 4 байта (страница) 16 байт (блок) 4 байта (SLIX2)
Auth Нет Да, посекторно Нет
NDEF Type 2 Не поддерживает Type 5
Ридер RC522 RC522 PN5180

Алгоритм записи

void writeTag(const WritePacket& packet) {
  uint8_t blob[MAX_SIZE];
  size_t len = base64_decode(packet.blobBase64, blob);

  switch (packet.tech) {
    case TECH_TYPE2_NTAG:
      writeType2(blob, len, packet.startAddr);
      break;
    case TECH_MIFARE_CLASSIC:
      writeMifareClassic(blob, len, packet.auth.keys);
      break;
    case TECH_ISO15693:
      writeISO15693(blob, len, packet.tagInfo.blockSize, packet.startAddr);
      break;
  }
}

Формат WritePacket

interface WritePacket {
  tech: 'type2_ntag' | 'mifare_classic_1k' | 'nfcv_iso15693';

  write: {
    chunkSize: number;
    startAddr: number;
    totalSize: number;
  };

  auth?: {
    keyType: 'A' | 'B';
    keys: { [sector: string]: string };
  };

  tagInfo?: {
    model: string;
    blockSize: number;
    totalBlocks: number;
  };

  format: 'ndef_type2' | 'ndef_type5' | 'raw' | 'openprinttag';
  blobBase64: string;
}

Примеры

NTAG215

{
  "tech": "type2_ntag",
  "write": { "chunkSize": 4, "startAddr": 4, "totalSize": 492 },
  "format": "ndef_type2",
  "blobBase64": "AwAA1QEBVRgBaHR0cHM6Ly9pZHJ5ZXI..."
}

ISO15693 (SLIX2)

{
  "tech": "nfcv_iso15693",
  "tagInfo": { "model": "ICODE_SLIX2", "blockSize": 4, "totalBlocks": 80 },
  "write": { "chunkSize": 4, "startAddr": 0, "totalSize": 316 },
  "format": "ndef_type5",
  "blobBase64": "4UAAQAMADVEBVRgBaHR0cHM6Ly9pZHJ5ZXI..."
}

Примечание: - для ICODE SLIX2 в проекте используется геометрия 80 блоков по 4 байта; - последний блок зарезервирован под системный счётчик, поэтому полезная ёмкость для данных составляет 79 * 4 = 316 байт; - startAddr = 0 означает полный бинарный образ, включающий Type 5 CC в первом пользовательском блоке.

Безопасность

MIFARE Classic: Ключи хранятся только на MCU, Backend передает номера секторов без ключей.

Workflow

  1. MCU определяет тег → отправляет тип Backend
  2. Backend отвечает с возможностями
  3. Пользователь выбирает катушку для записи
  4. Backend формирует WritePacket
  5. MCU записывает и подтверждает

Ограничения

  • Фрагментированные кадры не интегрированы в MCU
  • MQTT команда write_rfid не реализована
  • Результаты verify ещё не вынесены в отдельные backend/result-коды, хотя сама проверка чтением после записи в прошивке уже есть