2

When I make any GET request to my shield, the only thing I get when I read the request is '\r\n'. I am sending query parameters, and when the request has been read in the past, there was the full http request.

EDIT: Could this be due to some memory issue? It seems to be fairly non-deterministic when it fails, and I have 69% of memory taken when the program starts.

/************************************************************
ESP8266_Shield_Demo.h
SparkFun ESP8266 AT library - Demo
Jim Lindblom @ SparkFun Electronics
Original Creation Date: July 16, 2015
https://github.com/sparkfun/SparkFun_ESP8266_AT_Arduino_Library

This example demonstrates the basics of the SparkFun ESP8266
AT library. It'll show you how to connect to a WiFi network,
get an IP address, connect over TCP to a server (as a client),
and set up a TCP server of our own.

Development environment specifics:
  IDE: Arduino 1.6.5
  Hardware Platform: Arduino Uno
  ESP8266 WiFi Shield Version: 1.0

This code is released under the MIT license.

Distributed as-is; no warranty is given.
************************************************************/

//////////////////////
// Library Includes //
//////////////////////
// SoftwareSerial is required (even you don't intend on
// using it).
#include <SoftwareSerial.h> 
#include <SparkFunESP8266WiFi.h>

//////////////////////////////
// WiFi Network Definitions //
//////////////////////////////
// Replace these two character strings with the name and
// password of your WiFi network.
const char mySSID[] = "ssid";
const char myPSK[] = "pass";

const short out1 = 10;
const short out2 = 11;
const short out3 = 12;
const short out4 = 13;

bool on1 = false;
bool on2 = false;
bool on3 = false;
bool on4 = false;

//////////////////////////////
// ESP8266Server definition //
//////////////////////////////
// server object used towards the end of the demo.
// (This is only global because it's called in both setup()
// and loop()).
ESP8266Server server = ESP8266Server(80);

//////////////////
// HTTP Strings //
//////////////////
const String html = "HTTP/1.1 200 OK\r\n"
                          "Content-Type: text/html\r\n"
                          "Connection: close\r\n\r\n"
                          "<!DOCTYPE HTML>\r\n"
                          "<html>\r\n"
                          "<link rel=\"icon\" href=\"data:,\">\r\n"
                          "<a href=\"/?toggle=1\"><button>Toggle 1</button></a>\r\n"
                          "<a href=\"/?toggle=2\"><button>Toggle 2</button></a>\r\n"
                          "<a href=\"/?toggle=3\"><button>Toggle 3</button></a>\r\n"
                          "<a href=\"/?toggle=4\"><button>Toggle 4</button></a>\r\n"
                          "</html>\r\n";

// All functions called from setup() are defined below the
// loop() function. They modularized to make it easier to
// copy/paste into sketches of your own.
void setup() 
{
  // Set pins
  pinMode(out1, OUTPUT);
  pinMode(out2, OUTPUT);
  pinMode(out3, OUTPUT);
  pinMode(out4, OUTPUT);

  digitalWrite(out1, LOW);
  digitalWrite(out2, LOW);
  digitalWrite(out3, LOW);
  digitalWrite(out4, LOW);

  // Serial Monitor is used to control the demo and view
  // debug information.
  Serial.begin(9600);

  // initializeESP8266() verifies communication with the WiFi
  // shield, and sets it up.
  initializeESP8266();

  // connectESP8266() connects to the defined WiFi network.
  connectESP8266();

  // displayConnectInfo prints the Shield's local IP
  // and the network it's connected to.
  displayConnectInfo();

  serverSetup();
}

void loop() 
{
  serverDemo();
}

void initializeESP8266()
{
  // esp8266.begin() verifies that the ESP8266 is operational
  // and sets it up for the rest of the sketch.
  // It returns either true or false -- indicating whether
  // communication was successul or not.
  // true
  int test = esp8266.begin();
  if (test != true)
  {
    Serial.println(F("Error talking to ESP8266."));
    errorLoop(test);
  }
  Serial.println(F("ESP8266 Shield Present"));
}

void connectESP8266()
{
  // The ESP8266 can be set to one of three modes:
  //  1 - ESP8266_MODE_STA - Station only
  //  2 - ESP8266_MODE_AP - Access point only
  //  3 - ESP8266_MODE_STAAP - Station/AP combo
  // Use esp8266.getMode() to check which mode it's in:
  int retVal = esp8266.getMode();
  if (retVal != ESP8266_MODE_STA)
  { // If it's not in station mode.
    // Use esp8266.setMode([mode]) to set it to a specified
    // mode.
    retVal = esp8266.setMode(ESP8266_MODE_STA);
    if (retVal < 0)
    {
      Serial.println(F("Error setting mode."));
      errorLoop(retVal);
    }
  }
  Serial.println(F("Mode set to station"));

  // esp8266.status() indicates the ESP8266's WiFi connect
  // status.
  // A return value of 1 indicates the device is already
  // connected. 0 indicates disconnected. (Negative values
  // equate to communication errors.)
  retVal = esp8266.status();
  if (retVal <= 0)
  {
    Serial.print(F("Connecting to "));
    Serial.println(mySSID);
    // esp8266.connect([ssid], [psk]) connects the ESP8266
    // to a network.
    // On success the connect function returns a value >0
    // On fail, the function will either return:
    //  -1: TIMEOUT - The library has a set 30s timeout
    //  -3: FAIL - Couldn't connect to network.
    retVal = esp8266.connect(mySSID, myPSK);
    if (retVal < 0)
    {
      Serial.println(F("Error connecting"));
      errorLoop(retVal);
    }
  }
}

void displayConnectInfo()
{
  char connectedSSID[24];
  memset(connectedSSID, 0, 24);
  // esp8266.getAP() can be used to check which AP the
  // ESP8266 is connected to. It returns an error code.
  // The connected AP is returned by reference as a parameter.
  int retVal = esp8266.getAP(connectedSSID);
  if (retVal > 0)
  {
    Serial.print(F("Connected to: "));
    Serial.println(connectedSSID);
  }

  // esp8266.localIP returns an IPAddress variable with the
  // ESP8266's current local IP address.
  IPAddress myIP = esp8266.localIP();
  Serial.print(F("My IP: ")); Serial.println(myIP);
}

void serverSetup()
{
  // begin initializes a ESP8266Server object. It will
  // start a server on the port specified in the object's
  // constructor (in global area)
  server.begin();
  Serial.print(F("Server started! Go to "));
  Serial.println(esp8266.localIP());
  Serial.println();
}

void serverDemo()
{
  // available() is an ESP8266Server function which will
  // return an ESP8266Client object for printing and reading.
  // available() has one parameter -- a timeout value. This
  // is the number of milliseconds the function waits,
  // checking for a connection.
  ESP8266Client client = server.available(500);

  if (client) 
  {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    String req;
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        req += c;
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) 
        {
          Serial.println(req);
          if (req.indexOf("toggle=1") != -1){
            if (on1){
              Serial.println(F("TURN 1 ON"));
              digitalWrite(out1, LOW);
            }
            else {
              Serial.println(F("TURN 1 OFF"));
              digitalWrite(out1, HIGH);
            }
            on1 = !on1;
          }
          else if (req.indexOf("toggle=2") != -1){
            if (on2){
              digitalWrite(out2, LOW);
              Serial.println(F("TURN 2 OFF"));
            }
            else {
              Serial.println(F("TURN 2 ON"));
              digitalWrite(out2, HIGH);
            }
            on2 = !on2;
          }
          else if (req.indexOf("toggle=3") != -1){
            if (on3){
              Serial.println(F("TURN 3 OFF"));
              digitalWrite(out3, LOW);
            }
            else {
              Serial.println(F("TURN 3 ON"));
              digitalWrite(out3, HIGH);
            }
            on3 = !on3;
          }
          else if (req.indexOf("toggle=4") != -1){
            if (on4){
              Serial.println(F("TURN 4 OFF"));
              digitalWrite(out4, LOW);
            }
            else {
              Serial.println(F("TURN 4 ON"));
              digitalWrite(out4, HIGH);
            }
            on4 = !on4;
          }

          // send html
          client.print(html);
          break;
        }
        if (c == '\n') 
        {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') 
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);

    // close the connection:
    client.stop();
  }

}

// errorLoop prints an error code, then loops forever.
void errorLoop(int error)
{
  Serial.print(F("Error: ")); Serial.println(error);
  Serial.println(F("Looping forever."));
  for (;;)
    ;
}

2 Answers 2

0

In serverDemo() you are setting currentLineIsBlank to true. Then you are reading in each char until you get to a \n at which point you are assuming the http request has ended.

boolean currentLineIsBlank = true;
....

// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank)

I think you want to set currentLineIsBlank to false to begin with ?...

3
  • no it's true to begin with, because if we get a \n, then we are at the end of the first blank line. If the first character is not \r or \n, then we set currentLineIsBlank = false because there is something on the line
    – holtc
    Nov 21, 2016 at 21:12
  • have you tried checking (Serial.print(c)) the value of c after reading it from client.read(); What are you seeing here as the request coming in... Nov 22, 2016 at 9:39
  • It's an issue with using String. I've made a bunch of changes to switch from String to char[], and it is working, thanks for helping
    – holtc
    Nov 22, 2016 at 16:24
0

It's an issue using String with arduino. I've changed to use char[] and now it is working fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.