1

I'm using an ESP8266 connected to an Arduino one via SoftwareSerial to make a post request to a node web server. The ESP8266 sends some data to the server and it should get back other data. The data arrives at the server correctly, but the response from the server is incomplete (it gets cut each time in a different way) and I can't access the body of the response from my Arduino sketch. The server sends the response correctly, as i've checked with hurl.

This is my code:

#include "SoftwareSerial.h"

String ssid ="ssid";
String password="pwd";
SoftwareSerial esp(3, 2);// RX, TX

ESP8266_Simple wifi(3,2);

String data;
String server = "server"; 
String uri = "uri";

String token = "token";

float temp_set = 15; //standard values
float temp_rec = 15;
String temp_set_s;
String temp_rec_s;

int activate = LED_BUILTIN; //pin for relay
int button_up = 4;
int button_down = 5;

unsigned long time;

//LCD
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// DHT11
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 6
#define DHTTYPE DHT22    
DHT_Unified dht(DHTPIN, DHTTYPE);

void setup() {
  esp.begin(9600);
  Serial.begin(9600);
  delay(10);

  reset();
  connectWifi();

  pinMode(activate, OUTPUT);
  pinMode(button_up, INPUT);
  pinMode(button_down, INPUT);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  //DHT setup
  dht.begin();
  sensor_t sensor;

  delay(500);
}

//reset the esp8266 module
void reset() {
    esp.println("AT+RST");
    delay(1000);
    if(esp.find("OK") ) Serial.println("Module Reset");

}

//connect to your wifi network
void connectWifi() {
    String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";

    esp.println(cmd);

    delay(4000);

    if(esp.find("OK")) {
        Serial.println("Connected!");
        time = millis();
    } else {
        connectWifi();
        Serial.println("Cannot connect to wifi"); 
    }
} 


void loop () {

  //temp_rec_s = String(temp_rec);
  //temp_set_s = String(temp_set);
  //data = "tempRec=" + temp_rec_s + "&tempSet=" + temp_set_s;
  //httppost();

  // dht data
  sensors_event_t event;  
  dht.temperature().getEvent(&event);
  temp_rec = event.temperature; 

  //temp_rec_s = String(temp_rec);
  //temp_set_s = String(temp_set);
  //data = "tempRec=" + temp_rec_s + "&tempSet" + temp_set_s;


  // to activate
  if(temp_set < temp_rec){
    digitalWrite(activate, LOW);
  } else{
    digitalWrite(activate, HIGH);
  }

  //function for physical buttons
  if((digitalRead(button_up)) == HIGH){
    temp_set = temp_set + 0.5;
    delay(100);
  }
  if((digitalRead(button_down)) == HIGH){
    temp_set = temp_set - 0.5;
    delay(100);
  }

  //shows temperature on display
  lcd.setCursor(0, 0);
  lcd.print("T rec " + String(temp_rec));

  //shows temperature on display
  lcd.setCursor(0, 1);
  lcd.print("T set " + String(temp_set));

  temp_rec_s = String(temp_rec);
  temp_set_s = String(temp_set);
  data = "tempRec=" + temp_rec_s + "&tempSet=" + temp_set_s + "&token=" + token;
  //Serial.println(data);
  if((millis() - time) >= 10000){
    httppost();
  }


  delay(200);
}

void httppost () {
    esp.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.

    if(esp.find("OK")) {
        Serial.println("TCP connection ready");
    } 
    delay(1000);

    String postRequest =
    "POST " + uri + " HTTP/1.0\r\n" +
    "Host: " + server + "\r\n" +
    "Accept: *" + "/" + "*\r\n" +
    "Content-Length: " + data.length() + "\r\n" +
    "Content-Type: application/x-www-form-urlencoded\r\n" +
    "\r\n" + data;

    String sendCmd = "AT+CIPSEND="; //determine the number of caracters to be sent.

    esp.print(sendCmd);
    esp.println(postRequest.length());

    Serial.println(postRequest);

    delay(500);

    if(esp.find(">")) {
        Serial.println("Sending.."); 
        esp.print(postRequest);

        String tmpResp = esp.readString();
        Serial.println(tmpResp);

        if(esp.find("SEND OK")) { 
            Serial.println("Packet sent");

            while(esp.available()) {
                String line = esp.readString();
                Serial.print(line);
            }

            // close the connection
            esp.println("AT+CIPCLOSE");

        }
    }
} 
  • Check that the file that is returning data ends with two line breaks like this `

    `. If it doesn't, add them, to ensure proper end of file flag. Also move the `while(esp.available()) { String line = esp.readString();...` above the `while (esp.available() == 0) {`. If none of this works try adding a `delay(1)` under `String line = esp.readString();`. Also, use `char` instead of `String`, like `char line = `. Let me know if any of this works
    – Ivan86 Jan 09 '18 at 21:52
  • Thank you very much! Adding tha delay and using char instead of string made it work! – ElectricPikka Jan 09 '18 at 22:05

1 Answers1

1

Put a delay(1) under the esp.readString() and use .read() instead with char like this:

while(esp.available())
{
    char line = esp.read();        // read one char at a time
    delay(1);                      // prevent freezing
    Serial.print(line);
    if (line == '\0') continue;    // terminate the `while` when end of the data
}

The .readString() method as pointed out by @gre_gor reads until there is no incoming data for 1 second.

So the better method is to use read() and char since you can test the char to see if you have reached the end of data character \0.

When using .read() consider using a custom timeout, because data can be delivered with delays so you might want to keep trying for a certain period of time if you haven't yet reached the end of data character \0, like this:

long int time = millis();       // current time
long int wait = 1000 * 10;      // wait 10 seconds before terminating the read process

while ((time + wait) > millis())
{
    while (esp.available())
    {
        char line = esp.read();
        delay(1);
        Serial.print(line);
        if (line == '\0') continue;
    }
}    
Ivan86
  • 5,695
  • 2
  • 14
  • 30
  • `esp.readString()` reads multiple characters and waits until there is no more data for 1 second and returns a `String` not a `char`. – gre_gor Jan 10 '18 at 19:49
  • @gre_gor you are right. The `.readString()` uses a `timeout` like you said. I am a arduino mega user with GSM shield, WiFi, and others but I use `char`, `.read()` and a `delimiter`. That's probably why I had it in my memory that it is a `char`. My mistake, I will fix it now. Thanks – Ivan86 Jan 10 '18 at 21:09
  • @AndreaLaGrotteria I'm glad you got it working. Peace – Ivan86 Jan 10 '18 at 21:45
  • I'm trying to get the body of the response, which is at the end of the response. Do you know how I can do it? I tried adding the line variable to a global char variable but it doesn't seem to work... – ElectricPikka Jan 13 '18 at 10:54
  • 1
    @AndreaLaGrotteria you can store the output in a variable instead of printing it, then after the while has finished you can use one of the substring methods to extract the content after a certain char . Check out how to get the index of a substring in a string here: [https://www.arduino.cc/StringSubstring](https://www.arduino.cc/en/Tutorial/StringSubstring) – Ivan86 Jan 13 '18 at 18:10