简体   繁体   中英

Weird behaviour while POSTing a JSON through arduino's ENC28J60 module

I've managed to set up a function to POST JSON data through my Arduino. I'm using webhook to test it and I'm experiencing some weird behaviour with it. The JSON data is not created where I would expect it to. Any help with explaining this would be appreciated.

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[700];
static uint32_t timer;

const char website[] PROGMEM = "webhook.site"; //my router's address

// called when the client request is complete
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
}

void setup () {
  Serial.begin(57600);
  Serial.println("\n[webClient]");

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
      Serial.println("x{\"city\":\"Paris\",\"temp\":18.5}"); /// << JSON message is created here, and the first character of the message is removed
  if (!ether.dhcpSetup())
//    Serial.println("DHCP failed");

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip); 
  ether.printIp("DNS: ", ether.dnsip); 

  if (!ether.dnsLookup(website))
//    Serial.println("DNS failed");

  ether.printIp("SRV: ", ether.hisip);
}

void loop () {
  ether.packetLoop(ether.packetReceive());

  if (millis() > timer) {
    timer = millis() + 5000;
    Serial.println();
    Serial.print("<<< REQ ");
    ether.httpPost(PSTR("/fe6f00eb-30ed-4b59-8908-fa3ec13c2485"), website, PSTR("Content-Type: application/json"),
       PSTR(""), my_callback); // PSTR("") because the message is created after .begin function is called
    }
}

The Arduino has two completely separate address spaces: program memory, and RAM. Normally, pointers point to RAM.

PSTR("hello") puts the string "hello" into program memory and returns its address within program memory. If you read from this pointer, you actually read from data memory at the same location, and get some completely unrelated data. You need to use pgm_read_byte to read from program memory (which the ENC28J60 library doesn't do).

Your PSTR("") happens to have the same address as the second byte of the string you are printing in setup .

The solution is to remove PSTR() around the POST data.

I'm not sure if it is documented which parameters need to be in program memory, but I found the function here which reads them. It appears that $F means to read a string from program memory and $S means to read a string from RAM. client_postval is read using $S .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM