njh / EtherCard

EtherCard is an IPv4 driver for the ENC28J60 chip, compatible with Arduino IDE
https://www.aelius.com/njh/ethercard/
GNU General Public License v2.0
1.03k stars 455 forks source link

Payload construction for ThingSpeak appears to be wrong #382

Open TheRealBrommer opened 4 years ago

TheRealBrommer commented 4 years ago

What i'm using it for/background:

I have a fish tank with several sensors and i want to send this over LAN (ENC28J60 chip) to ThingSpeak. I already have a set up with a Wemos Mini Pro, which uses the ESP8266 chip. This works like a treat. Now i'm building one for a LAN connection based on an Arduino Nano. Unlike the Wemos, memory is an issue. So i've gravitated to using EtherCard. UIPethernet works great, but i run out of memory. Cutting out UDP and "save" 5K memory doesn't works as ThingSpeak only works when it's enabled.

Issue:

The way EtherCard constructs the payload to send to ThingSpeak only works sporadically. Hence it is VERY unreliable. Constantly i get "500 Internal Server Error".

When i use the Wemos and look how the payload is constructed i figured i should be able to transfer this to be used with UIPethernet. I did and this works 99% of the time! Every now and then it drops a data point but that's OK.

What Ethercard does with that stash makes me think it is constructed wrongly 9maybe it worked well in the past, but not anymore). So my question is can this be changed/altered in such a way to resemble the attached WORKING sample of the UIPethernet payload (my code's a bit messy maybe, but i'm still fiddling it)?

Reason is i cannot use UIPethernet, as mentioned, as i run out of memory (well almost, but it corrupts it workings). So i HAVE to use EtherCard, but it hardly ever works. So obviously when i'm trying to monitor my fish tank conditions and i get 2 data points a day, that's of no use.

Payload construction using the UIPethernet library, with values of the sensors preset to test (>99% success) is shown below:

// // UIPEthernet TcpClient example. // UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based // Ethernet-shield. // UIPEthernet uses the fine uIP stack by Adam Dunkels adam@sics.se // This TcpClient example gets its local ip-address via dhcp and sets // up a tcp socket-connection to 192.168.0.1 port 5000 every 5 Seconds. // After sending a message it waits for a response. After receiving the // response the client disconnects and tries to reconnect after 5 seconds. // // Copyright (C) 2013 by Norbert Truchsess norbert.truchsess@t-online.de // // disable UDP (in utility/uipethernet-conf.h) to save 5K, but need static IP // re-enabled it as thingSpeak seems to need UDP

include

EthernetClient client;

// <<<<<<<<<<<<<< Thingspeak >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> const char server = "api.thingspeak.com"; const char api_key = "XXXXXXXXXXXXXXXX"; // API write key // <<<<<<<<<<<<<<<< Thingspeak >>>>>>>>>>>>>>>>>>>>>>>>>>>>

float pres = 0.995; float temp = 25; float volt = 4.1; float perc = 99; float ntu = 80; float TDS = 45; float TempTank = 25; float pHvalue = 7;

void setup() {

Serial.begin(9600);

uint8_t mac[6] = {0x74,0x69,0x69,0x2D,0x30,0x31}; //IPAddress ip(192,168,17,166); //IPAddress dnsServer(192,168,17,1); //IPAddress gateway(192,168,17,1); //IPAddress subnet(255,255,255,0); //Ethernet.begin(mac, ip, gateway, gateway, subnet);
Ethernet.begin(mac); //Configure IP address via DHCP Serial.print(F("LAN connected: ")); Serial.println(Ethernet.localIP());

}

void loop() {

// <<<<<<<<<<<<<<< Thingspeak >>>>>>>>>>>>>>>>>>>>>>>>>>>>

if (client.connect(server,80)) { Serial.println(F("Sending DATA to ThingSpeak .... OK"));

String postStr = ""; postStr+="GET /update?api_key="; postStr+=api_key;
postStr+="&field1="; postStr+=String(pres); postStr+="&field2="; postStr+=String(temp);
postStr+="&field3="; postStr+=String(volt); postStr+="&field4="; postStr+=String(perc); postStr+="&field5="; postStr+=String(ntu);
postStr+="&field6="; postStr+=String(TDS); postStr+="&field7="; postStr+=String(TempTank); postStr+="&field8="; postStr+=String(pHvalue); postStr+=" HTTP/1.1\r\nHost: a.c.d\r\nConnection: close\r\n\r\n"; postStr+=""; client.print(postStr); Serial.println(""); } else { Serial.println(F("Did NOT connect; reconnecting ....")); } while(client.available()){ String line = client.readStringUntil('\r'); Serial.print(line); }

// <<<<<<<<<<<<<<< Thingspeak >>>>>>>>>>>>>>>>>>>>>>>>  

delay(20000);

}

TheRealBrommer commented 4 years ago

No interest in fixing this !?

nuno-silva commented 4 years ago

Can you post the code that causes issues using EtherCard? We can not debug what we can not see :)

TheRealBrommer commented 4 years ago

It's the included thingspeak example in EtherCard/examples/thingspeak/:

// generate two fake values as payload - by using a separate stash, // we can determine the size of the generated message ahead of time // field1=(Field 1 Data)&field2=(Field 2 Data)&field3=(Field 3 Data)&field4=(Field 4 Data)&field5=(Field 5 Data)&field6=(Field 6 Data)&field7=(Field 7 Data)&field8=(Field 8 Data)&lat=(Latitude in Decimal Degrees)&long=(Longitude in Decimal Degrees)&elevation=(Elevation in meters)&status=(140 Character Message) byte sd = stash.create(); stash.print("field1="); stash.print(demo); //stash.print("&field2="); //stash.print(one); //stash.print("&field3="); //stash.print(msje); stash.save();

//Display data to be sent
Serial.println(demo);

// generate the header with payload - note that the stash size is used,
// and that a "stash descriptor" is passed in as argument using "$H"
Stash::prepare(PSTR("POST /update HTTP/1.0" "\r\n"
  "Host: $F" "\r\n"
  "Connection: close" "\r\n"
  "X-THINGSPEAKAPIKEY: $F" "\r\n"
  "Content-Type: application/x-www-form-urlencoded" "\r\n"
  "Content-Length: $D" "\r\n"
  "\r\n"
  "$H"),
website, PSTR(APIKEY), stash.size(), sd);