Преобразовать полезную нагрузку записи NDEF в строку для EthernetClient print () - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь сделать HTTP-запрос GET с данными, считанными из тега MIFARE NFC в формате NDEF.Мне не удается преобразовать данные байтового массива из тега в формат, который работает с функцией клиента Ethernet print().

Аппаратная настройка - это Arduino Uno с seeedstudio NFC Shield и Arduino ethernet shield.Я использую Ethernet, PN532 и библиотеку NfcAdapter.

Я пробовал несколько типов преобразования, используя char * и char[] вместо объекта String, но безуспешно.

Чтобы точно определить проблему, я выбрал случай, когда Serial.print() дает ожидаемый результат, а client.print() - нет.

Код основан на примере библиотеки PN532 NDEF 'ReadTagExtended' .

void loop(void)
{
    if (nfc.tagPresent()) // Do an NFC scan to see if an NFC tag is present
    {
        NfcTag tag = nfc.read(); // read the NFC tag
        if (tag.hasNdefMessage())
        {
            NdefMessage message = tag.getNdefMessage();
            for (int i = 0; i < message.getRecordCount(); i++)
            {
                NdefRecord record = message.getRecord(i);
                int payloadLength = record.getPayloadLength();
                byte payload[payloadLength];
                record.getPayload(payload);
                String tag_content = "";
                for(int i = 0; i<payloadLength; i++) {
                    tag_content += (char)payload[i];
                }
                Serial.println(tag_content); // prints the correct string
                request(tag_content);
            }
        }
    }
}

void request(String data) {
    EthernetClient client;

    // if you get a connection, report back via serial:
    if (client.connect(remote, 8080)) {
        client.print("GET /subaddress");
        client.print("?data=");
        client.print(data); // unfortunately empty
        client.println();
        client.println();

        while (client.connected()) {
        if (client.available()) {
            char c = client.read();
            Serial.print(c);
        }
    }
    client.stop();
    Serial.println(" OK");
    delay(100);
    } else {
        Serial.println("ERR");
        delay(100);
    }
}

При указанной выше настройке я получаю ожидаемый результат, используя Serial.println().Тем не менее, в (успешном) запросе data пусто.


Из комментариев (суммировано):

Печать типа записи (record.getType()) дает букву «U».payloadLength равно 4 для тега, содержащего строку «def».

1 Ответ

0 голосов
/ 16 февраля 2019

На основании информации, предоставленной вами в комментарии, тег содержит запись URI (которая, в свою очередь, содержит ваши данные).Проблема в вашем коде заключается в том, что вы непосредственно используете всю полезную нагрузку записи URI в виде строки.Тем не менее, запись URI содержит больше, чем просто строка.В частности, первый байт полезной нагрузки является байтом префикса (обычно непечатаемый символ).Таким образом, кажется, что Serial.println() (или, скорее, ваш последовательный приемник) просто пропускает этот символ.client.print() включит этот символ в HTTP-запрос и, следовательно, создаст недопустимый HTTP-запрос (который выглядит так, как если бы оставшиеся байты были пропущены).

Следовательно, вам придется следовать определению типа записи URI, чтобыдекодируйте полезную нагрузку в правильный URI перед его использованием:

NdefMessage message = tag.getNdefMessage();
for (int i = 0; i < message.getRecordCount(); ++i) {
    NdefRecord record = message.getRecord(i);
    if (record.getType() == "U") {
        String uri = "";
        int payloadLength = record.getPayloadLength();
        if (payloadLength > 0) {
            byte payload[payloadLength];
            record.getPayload(payload);

            switch (payload[0]) {
                case 0x000: break;
                case 0x001: uri += "http://www."; break;
                case 0x002: uri += "https://www."; break;
                case 0x003: uri += "http://"; break;
                case 0x004: uri += "https://"; break;
                case 0x005: uri += "tel:"; break;
                case 0x006: uri += "mailto:"; break;
                case 0x007: uri += "ftp://anonymous:anonymous@"; break;
                case 0x008: uri += "ftp://ftp."; break;
                case 0x009: uri += "ftps://"; break;
                case 0x00A: uri += "sftp://"; break;
                case 0x00B: uri += "smb://"; break;
                case 0x00C: uri += "nfs://"; break;
                case 0x00D: uri += "ftp://"; break;
                case 0x00E: uri += "dav://"; break;
                case 0x00F: uri += "news:"; break;
                case 0x010: uri += "telnet://"; break;
                case 0x011: uri += "imap:"; break;
                case 0x012: uri += "rtsp://"; break;
                case 0x013: uri += "urn:"; break;
                case 0x014: uri += "pop:"; break;
                case 0x015: uri += "sip:"; break;
                case 0x016: uri += "sips:"; break;
                case 0x017: uri += "tftp:"; break;
                case 0x018: uri += "btspp://"; break;
                case 0x019: uri += "btl2cap://"; break;
                case 0x01A: uri += "btgoep://"; break;
                case 0x01B: uri += "tcpobex://"; break;
                case 0x01C: uri += "irdaobex://"; break;
                case 0x01D: uri += "file://"; break;
                case 0x01E: uri += "urn:epc:id:"; break;
                case 0x01F: uri += "urn:epc:tag:"; break;
                case 0x020: uri += "urn:epc:pat:"; break;
                case 0x021: uri += "urn:epc:raw:"; break;
                case 0x022: uri += "urn:epc:"; break;
                case 0x023: uri += "urn:nfc:"; break;
                default: break;
            }
            for (int j = 1; j < payloadLength; ++j) {
                uri += (char)payload[i]; // NOTE: this is wrong since the string is UTF-8 encoded (but we translate it byte-by-byte)
            }
        }
        Serial.println(uri);
        request(uri);
    }
}

Имейте в виду, что есть еще несколько проблем с решением выше:

  • Строковая часть URI (байты, начинающиеся со смещения 1), фактически кодируются в кодировке UTF-8.Однако мы рассматриваем его так, как если бы он был (более или менее) в кодировке ASCII.Я не нашел ни одной простой библиотеки для правильного преобразования байтовых массивов в строковое представление в кодировке UTF-8 на Arduino.
  • Если ваш результирующий URI содержит символы, которые имеют особое значение в URL (например, "/",":", "&" и т. д.), вам необходимо их кодировать (см., например, здесь ), прежде чем добавлять строку в запрос GET.В противном случае результирующий URI запроса GET может не соответствовать ожидаемому.
  • String, безусловно, не лучший выбор с точки зрения эффективности памяти.
...