Flashing RED & rebooting after about 15 seconds (sketch included) [SOLVED]

Each time I run this sketch it works OK for about 10 seconds, then the core LED starts flashing RED, turns off, flashes red again, turns off and the core restarts. Sometimes when the core restarts, the loop() is still running, but the HTTP requests are no longer coming through. In this case, it never restarts (but isn’t very useful in this state)

I’ve built it locally and using the cloud editor and the results are the same. :confused:

Code:

RestClient.h

#include "application.h"

class RestClient {

  public:
    RestClient(const char* host);
    RestClient(const char* _host, int _port);

    //Client Setup
    void dhcp();
    int begin(byte*);

    //Generic HTTP Request
    int request(const char* method, const char* path,
                const char* body, String* response);
    // Set a Request Header
    void setHeader(const char*);
    // GET path
    int get(const char*);
    // GET path and response
    int get(const char*, String*);

    // POST path and body
    int post(const char* path, const char* body);
    // POST path and body and response
    int post(const char* path, const char* body, String*);

    // PUT path and body
    int put(const char* path, const char* body);
    // PUT path and body and response
    int put(const char* path, const char* body, String*);

    // DELETE path
    int del(const char*);
    // DELETE path and body
    int del(const char*, const char*);
    // DELETE path and response
    int del(const char*, String*);
    // DELETE path and body and response
    int del(const char*, const char*, String*);

  private:
    TCPClient client;
    int readResponse(String*);
    void write(const char*);
    const char* host;
    int port;
    int num_headers;
    const char* headers[10];
    boolean contentTypeSet;
};

RestClient.cpp

/**
 ******************************************************************************
 * @file    RestClient.cpp
 * 
 * details: https://github.com/llad/spark-restclient
 * 
 * credit: https://github.com/csquared/arduino-restclient
 * 
 ******************************************************************************

*/

#include "RestClient.h"

#ifdef HTTP_DEBUG
#define HTTP_DEBUG_PRINT(string) (Serial.print(string))
#endif

#ifndef HTTP_DEBUG
#define HTTP_DEBUG_PRINT(string)
#endif

RestClient::RestClient(const char* _host){
  host = _host;
  port = 80;
  num_headers = 0;
  contentTypeSet = false;
}

RestClient::RestClient(const char* _host, int _port){
  host = _host;
  port = _port;
  num_headers = 0;
  contentTypeSet = false;
}

// GET path
int RestClient::get(const char* path){
  return request("GET", path, NULL, NULL);
}

//GET path with response
int RestClient::get(const char* path, String* response){
  return request("GET", path, NULL, response);
}

// POST path and body
int RestClient::post(const char* path, const char* body){
  return request("POST", path, body, NULL);
}

// POST path and body with response
int RestClient::post(const char* path, const char* body, String* response){
  return request("POST", path, body, response);
}

// PUT path and body
int RestClient::put(const char* path, const char* body){
  return request("PUT", path, body, NULL);
}

// PUT path and body with response
int RestClient::put(const char* path, const char* body, String* response){
  return request("PUT", path, body, response);
}

// DELETE path
int RestClient::del(const char* path){
  return request("DELETE", path, NULL, NULL);
}

// DELETE path and response
int RestClient::del(const char* path, String* response){
  return request("DELETE", path, NULL, response);
}

// DELETE path and body
int RestClient::del(const char* path, const char* body ){
  return request("DELETE", path, body, NULL);
}

// DELETE path and body with response
int RestClient::del(const char* path, const char* body, String* response){
  return request("DELETE", path, body, response);
}

void RestClient::write(const char* string){
  HTTP_DEBUG_PRINT(string);
  client.print(string);
}

void RestClient::setHeader(const char* header){
  headers[num_headers] = header;
  num_headers++;
}

// The mother- generic request method.
//
int RestClient::request(const char* method, const char* path,
                  const char* body, String* response){

  HTTP_DEBUG_PRINT("HTTP: connect\n");

  if(client.connect(host, port)){
    HTTP_DEBUG_PRINT("HTTP: connected\n");
    HTTP_DEBUG_PRINT("REQUEST: \n");
    // Make a HTTP request line:
    write(method);
    write(" ");
    write(path);
    write(" HTTP/1.1\r\n");
    for(int i=0; i<num_headers; i++){
      write(headers[i]);
      write("\r\n");
    }
    write("Host: ");
    write(host);
    write("\r\n");
    write("Connection: close\r\n");

    if(body != NULL){
      char contentLength[30];
      sprintf(contentLength, "Content-Length: %d\r\n", strlen(body));
      write(contentLength);

      if(!contentTypeSet){
        write("Content-Type: application/x-www-form-urlencoded\r\n");
      }
    }

    write("\r\n");

    if(body != NULL){
      write(body);
      write("\r\n");
      write("\r\n");
    }

    //make sure you write all those bytes.
    delay(100);

    HTTP_DEBUG_PRINT("HTTP: call readResponse\n");
    int statusCode = readResponse(response);
    HTTP_DEBUG_PRINT("HTTP: return readResponse\n");

    //cleanup
    HTTP_DEBUG_PRINT("HTTP: stop client\n");
    num_headers = 0;
    client.stop();
    delay(50);
    HTTP_DEBUG_PRINT("HTTP: client stopped\n");

    return statusCode;
  }else{
    HTTP_DEBUG_PRINT("HTTP Connection failed\n");
    return 0;
  }
}

int RestClient::readResponse(String* response) {

  // an http request ends with a blank line
  boolean currentLineIsBlank = true;
  boolean httpBody = false;
  boolean inStatus = false;

  char statusCode[4];
  int i = 0;
  int code = 0;

  if(response == NULL){
    HTTP_DEBUG_PRINT("HTTP: NULL RESPONSE POINTER: \n");
  }else{
    HTTP_DEBUG_PRINT("HTTP: NON-NULL RESPONSE POINTER: \n");
  }

  HTTP_DEBUG_PRINT("HTTP: RESPONSE: \n");
  while (client.connected()) {
    HTTP_DEBUG_PRINT(".");
    if (client.available()) {
      HTTP_DEBUG_PRINT(",");

      char c = client.read();
      HTTP_DEBUG_PRINT(c);

      if(c == ' ' && !inStatus){
        inStatus = true;
      }

      if(inStatus && i < 3 && c != ' '){
        statusCode[i] = c;
        i++;
      }
      if(i == 3){
        statusCode[i] = '\0';
        code = atoi(statusCode);
      }

      //only write response if its not null
      if(httpBody){
        if(response != NULL) response->concat(c);
      }
      if (c == '\n' && httpBody){
        HTTP_DEBUG_PRINT("HTTP: return readResponse2\n");
        return code;
      }
      if (c == '\n' && currentLineIsBlank) {
        httpBody = true;
      }
      if (c == '\n') {
        // you're starting a new lineu
        currentLineIsBlank = true;
      }
      else if (c != '\r') {
        // you've gotten a character on the current line
        currentLineIsBlank = false;
      }
    }
  }

  HTTP_DEBUG_PRINT("HTTP: return readResponse3\n");
  return code;
}

sketch.ino

#include "RestClient.h"

RestClient lightServer = RestClient("10.0.0.6",56780);
String response;


void setup()
{

}

void loop()
{
  delay(2000);
  lightServer.put("/lights/all/toggle", "", &response);
}

Hmmm, on closer inspection it seems to be a problem with the RestClient library.

I just used the TCPClient directly (code below) and it seems to be fine. Will leave it run overnight to be sure.

 if (client.connect(server, 56780)) 
  {
    client.println("PUT /lights/d073d5009089/toggle HTTP/1.1");
    client.println("Host: someurl.com");
    client.println("User-Agent: Spark/? Test/0");
    client.println("Connection: Close");
    client.println("Content-Length: 0");
    client.println();

    while(!client.available());

    // while(client.available()) 
    // {
    //   char c = client.read();
    //   Serial.print(c);
    // }

    // Serial.println();

    client.stop();
  } 

Hi @dermotos

The flashing red LED is a panic code. It flashed SOS (… —…) and then a number, and then SOS again. The number indicates what kind of panic you had, but I would think that you ran out of memory, which is 8 flashes.

The core is supposed to reboot itself after a panic but it can’t always do that depending on how badly things went wrong.

HI again @dermotos

It looks like the RestClient library concatenates the response into the String you pass in. I don’t see where you ever do anything with this in the sketch, so the responses just keep building up and building up in the response String. I think if you want to use the RestClient library, you need to set that string back to empty after you call the library or the library also has a put method without response; maybe that is what you wanted in this case?

2 Likes

yeah, @bko is right on. Try this:

#include "RestClient.h"

RestClient lightServer = RestClient("10.0.0.6",56780);

void setup()
{

}

void loop()
{
  delay(2000);
  lightServer.put("/lights/all/toggle", "");
} 
3 Likes

That makes sense. Thanks for your help. Will try it out and report back.

edit: Yep! Solved the issue! :smile:

1 Like