gpt4 book ai didi

c++ - 将 NDEF 记录有效负载转换为 EthernetClient print() 的字符串

转载 作者:行者123 更新时间:2023-11-30 04:52:22 33 4
gpt4 key购买 nike

我尝试使用从 NDEF 格式的 MIFARE NFC 标签读取的数据发出 HTTP GET 请求。我无法将标签中的字节数组数据转换为适用于以太网客户端 print() 函数的格式。

硬件设置是带有 seeedstudio NFC Shield 和 Arduino 以太网扩展板的 Arduino Uno。我使用以太网、PN532 和 NfcAdapter 库。

我尝试了几种类型的转换,使用 char *char[] 而不是 String 对象,但没有成功。

为了查明问题,我选择了一个案例,其中 Serial.print() 给出了预期的结果,但 client.print() 没有。

代码基于PN532 NDEF library example '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”。对于包含字符串“def”的标记,payloadLength 为 4。

最佳答案

根据您在评论中提供的信息,该标签包含一个 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[j]; // 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。不过,我还没有找到任何简单的库来将字节数组正确地转换为 Arduino 上的 UTF-8 编码字符串表示形式。
  • 如果生成的 URI 包含在 URL 中具有特殊含义的字符(例如“/”、“:”、“&”等),您需要在附加GET 请求的字符串。否则,GET 请求的结果 URI 可能不是您所期望的。
  • String 在内存效率方面当然不是最佳选择。

关于c++ - 将 NDEF 记录有效负载转换为 EthernetClient print() 的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54446038/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com