[SOLVED] 400 bad resquest Error using method GET


#1

Hi @jotathebest

I’m using method GET whit a module wifi ESP-07 / ESP8266 and my Arduino Pro mini but that always answers me with the 400 bad resquest Error and I don’t know what I’m doing wrong. Could you help me please ?


#2

Hello @YudhistiraGM,

An error 400 means that you are not sending properly the variables inside your payload. Please refer to our API to know the meaning of every response code. Also check that you are not using any special character, blank space or underscore character as your variables’ labels.

In this video you can see how to build properly a payload.

Regards.


#3

Friend @jotathebest

I have read all the information about the different forms of the GET method … I have tried in many ways but it always sends me the same error.

This is my code:

Serial.println("\n*********************************************************************************\n");
   Serial.println("Getting your variable: \n");

   Flush();

   Serial.println("AT+CIPSTART=4,\"TCP\",\"things.ubidots.com\",80");
   delay(2500);

   debug();
   Flush();

   Serial.println("AT+CIPSEND=4," + String(SEND)); // 128 - 154 bad resquest End (Varibles GET) // 134 - 160 bad resquest End (Values GET) // 15 - 128
   delay(500);

   debug();
   Flush();
    
   Serial.println(GET);
   Serial.println(host);
   delay(10);

//   Serial.println("AT+CIPCLOSE=5");
//   delay(1500);
   
   while (Serial.available()) {
    
      get_response = Serial.readString();
   }

   Serial.println(get_response);
   
   bodyPosinit = 4 + get_response.indexOf("\r\n\r\n");
   get_response = get_response.substring(bodyPosinit);

   bodyPosinit = 9 + get_response.indexOf("\"value\":");
   bodyPosend = get_response.indexOf(", \"timestamp\"");
   get_response = get_response.substring(bodyPosinit,bodyPosend);
   num = get_response.toInt();

   return num;

And that always response me:

Getting your variable: 

AT+CIPSTART=4,"TCP","things.ubidots.com",80
AT+CIPSTART=4,"TCP","things.ubidots.com",80

4,CONNECT

OK

AT+CIPSEND=4,128
AT+CIPSEND=4,128


OK
> 
GET /api/v1.6/variables/5991340ec03f976606f14f0e/?token=A1E-E5MzsbUe5I2jSAkjEwniUaxA2alEeK HTTP/1.1
Host: things.ubidots.com


busy s...

Recv 128 bytes
Host: things.ubidots.com

busy s...

SEND OK

+IPD,4,183:HTTP/1.1 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>

4,CLOSED


Value: 0

********************************************************************************

I don’t understand. I’m following the methodology that says in the documentation to do my json and still, it always gives me the same result.


#4

Greetings @YudhistiraGM, you can use the code below as reference to retrieve data from Ubidots:

/********************************
 * Libraries included
 *******************************/
#include <ESP8266WiFi.h>
/********************************
 * Constants and objects
 *******************************/
namespace {
  const char * SSID_NAME = "...."; // Put here your SSID name
  const char * SSID_PASS = "...."; // Put here your Network password
  const char * SERVER = "things.ubidots.com";
  const char * TOKEN = "...."; // Assign your Ubidots TOKEN
  const char * DEVICE_LABEL = "...."; // Assign the device label to get the values of the variables
  const char * VAR_LABEL = "...."; // Assign the variable label to get the last value
  const char * USER_AGENT = "ESP8266";
  const char * VERSION = "1.0";
  const int PORT = 80;
}

WiFiClient client;

/********************************
 * Auxiliar Functions
 *******************************/

/*
   this method makes a HTTP connection to the server
   and send request to get a data
*/

float getData(const char * variable_label) {
  /* Assigns the constans as global on the function */
  char* response; // Array to store parsed data
  char* serverResponse; // Array to store values
  float num;
  char resp_str[700]; // Array to store raw data from the server
  uint8_t j = 0;
  uint8_t timeout = 0; // Max timeout to retrieve data
  uint8_t max_retries = 0; // Max retries to make attempt connection

  /* Builds the request GET - Please reference this link to know all the request's structures https://ubidots.com/docs/api/ */
  char* data = (char *) malloc(sizeof(char) * 220);
  sprintf(data, "GET /api/v1.6/devices/%s/%s/lv", DEVICE_LABEL, variable_label);
  sprintf(data, "%s HTTP/1.1\r\n", data);
  sprintf(data, "%sHost: things.ubidots.com\r\n", data);
  sprintf(data, "%sUser-Agent: %s/%s\r\n", data, USER_AGENT, VERSION);
  sprintf(data, "%sX-Auth-Token: %s\r\n", data, TOKEN);
  sprintf(data, "%sConnection: close\r\n\r\n", data);

  /* Initial connection */
  client.connect(SERVER, PORT);
  
  /* Reconnect the client when is disconnected */
  while (!client.connected()) {
    Serial.println("Attemping to connect");
    if (client.connect(SERVER, PORT)) {
      break;
    }

    // Tries to connect five times as max
    max_retries++;
    if (max_retries > 5) {
      Serial.println("Could not connect to server");
      free(data);
      return NULL;
    }
    delay(5000);
  }

  /* Make the HTTP request to the server*/
  client.print(data);

  /* Reach timeout when the server is unavailable */
  while (!client.available() && timeout < 2000) {
    timeout++;
    delay(1);
    if (timeout >= 2000) {
      Serial.println(F("Error, max timeout reached"));
      client.stop();
      free(data);
      return NULL;
    }
  }

  /* Reads the response from the server */
  int i = 0;
  while (client.available()) {
    char c = client.read();
    //Serial.write(c); // Uncomment this line to visualize the response from the server
    if (c == -1) {
      Serial.println(F("Error reading data from server"));
      client.stop();
      free(data);
      return NULL;
    }
    resp_str[i++] = c;
  }

  /* Parses the response to get just the last value received */
  response = strtok(resp_str, "\r\n");
  while(response!=NULL) {
    j++;
    //printf("%s", response);
    response = strtok(NULL, "\r\n");
    if (j == 10) {
      if (response != NULL) {
        serverResponse = response;
      }
      j = 0;
    }
  }

  /* Converts the value obtained to a float */
  num = atof(serverResponse);
  free(data);
  /* Removes any buffered incoming serial data */
  client.flush();
  /* Disconnects the client */
  client.stop();
  /* Returns de last value of the variable */
  return num;
}

/********************************
 * Main Functions
 *******************************/

void setup() {
  Serial.begin(115200);
  //Serial.println("Serial init...");
  /* Connects to AP */
  WiFi.begin(SSID_NAME, SSID_PASS);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }

  WiFi.setAutoReconnect(true);
  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());

}

void loop() {
  float value = getData(VAR_LABEL);
  
  Serial.print("value: ");
  Serial.print(value);
  delay(1000);
}

Also you can use our library for the ESP8266, in that way you do not have to worry about to build properly the structure inside your firmware to retrieve data.

Regards


#5

Greetings @jotathebest , thanks a lot for your help but right now I’m trying to create my own library that facilitates communication with your Ubidots page. I already found that, my problem was in the amount of bytes I sent to send my GET request.

Kind Regards.


#6

Hi there @YudhistiraGM, I am glad to know that you made it work. If you can share with the community your code and solution it will be great!

Regards


#7

With pleasure, friend @jotathebest

Just modify the serial buffer RX of the HardwareSerial.h library, because its size to receive the response from Ubidots is too large to save it without problems, it gets bigger to get the value we need. Within the program I make a comment at the beginning where it says that for this type of GET must be changed to 425.

#define SERIAL_RX_BUFFER_SIZE 425

The address of the library is here:

C: \ Program Files (x86) \ Arduino \ hardware \ arduino \ avr \ cores \ arduino

The library is opened, modified and saved and ready … the program is compiled and ready!

#define ssid "INFINITUMCF79"
#define password "3462123233"

#define id  "5991340ec03f976606f14f0e"  // slider_id
#define token  "A1E-E5MzsbUe5I2jSAkjEwniUaxA2alEeK"  // Put here your Ubidots TOKEN

// 425 buffer RX necesario para un variable GET

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  Serial.println("\nModule Settings WiFi ESP8266 ESP-07\n");

  sendCmd("AT+RESTORE", "OK", "R", 1000, 1);
  sendCmd("AT+RST", "OK", "WiFi Module Ready!", 1000, 2);
  sendCmd("AT+CWMODE=3", "OK", "Ap+Station Mode", 1000, 1);    
  sendCmd("AT+CWJAP=\""ssid"\",\""password"\"", "CONNECTED", "Successful WiFi Connection!", 5000, 1);   
  sendCmd("AT+CIFSR", "OK", " ", 2500, 3);
  sendCmd("AT+CIPMUX=1", "OK", "Enable Multiple Connections!", 500, 1); 
  sendCmd("AT+GMR", "OK", " ", 1000, 4);
}

void loop() {
  // put your main code here, to run repeatedly:

  int value = getVal();
  Serial.write(0x1A);
  Serial.print(">> Value: ");
  Serial.println(value);
  Serial.println(" ");
  delay(2500);  

  Serial.println("TCP Connection Closed!");
}

void sendCmd(char* cmd, char* f, char* ans, int t, int selected) {

  String response;
  boolean Er = true;

  Serial.println(cmd);
  delay(t);

  if (selected == 1 || selected == 2) {
    
    while(Serial.available()) {

      if(Serial.find(f)) {

        if(ans == "R") {
          
          delay(500);
          Serial.print(".");
          delay(500);
          Serial.print(".");
          delay(500);
          Serial.println(".\n");
          delay(1000);
        }
        else {
          
          Serial.println(ans);
          delay(500);
        }
        
        Er = false;
      }
    }  
  }

  if(selected == 3) {

    while(Serial.available()) {

      response = Serial.readStringUntil(f);
      
      if(response) {
        
        Er = false;
      }
    }
    
    //Serial.println(response);
    
    int APIPadd = response.indexOf("APIP,\"");                      
    String APIPaddStr = response.substring(APIPadd+6);
    APIPaddStr = APIPaddStr.substring(0,11);

    Serial.print("AP_IP: ");
    Serial.println(APIPaddStr);

    int APMACadd = response.indexOf("APMAC,\"");                      
    String APMACaddStr = response.substring(APMACadd+7);
    APMACaddStr = APMACaddStr.substring(0,17);

    Serial.print("AP_MAC: ");
    Serial.println(APMACaddStr);

    int STAIPadd = response.indexOf("STAIP,\"");                      
    String STAIPaddStr = response.substring(STAIPadd+7);
    STAIPaddStr = STAIPaddStr.substring(0,12);

    Serial.print("STA_IP: ");
    Serial.println(STAIPaddStr);

    int STAMACadd = response.indexOf("STAMAC,\"");                     
    String STAMACaddStr = response.substring(STAMACadd+8);
    STAMACaddStr = STAMACaddStr.substring(0,17);

    Serial.print("STA_MAC: ");
    Serial.println(STAMACaddStr); 

    delay(1000);   
  }

  if(selected == 4) {

    while(Serial.available()) {

      response = Serial.readStringUntil(f);
      
      if(response) {
        
        Er = false;
      }
    }

    int atVersion = response.indexOf("AT version:");                      
    String atVersionStr = response.substring(atVersion+11);
    atVersionStr = atVersionStr.substring(0,7);

    Serial.print("AT version: ");
    Serial.println(atVersionStr);

    int sdkVersion = response.indexOf("SDK version:");                      
    String sdkVersionStr = response.substring(sdkVersion+12);
    sdkVersionStr = sdkVersionStr.substring(0,7);

    Serial.print("SDK version: ");
    Serial.println(sdkVersionStr);
  }
  
  if(Er == true) {
      
    Serial.println("Error");
    delay(500);

    if(f == "CONNECTED") {
        
      if(Er == true) {
          
        Serial.println("WiFi Disconnected!");
        delay(500);
      }
    }
  }  
}

//**************************************************************************

int getVal() { 

   String get_response, GET;
   int bodyPosinit, bodyPosend, num, SEND = 148; // Values = 148 bytes to SEND

   //  Varibles GET
   GET = "GET /api/v1.6/variables/" + String(id1) + "/values/?page_size=1&token=" + String(token) + " HTTP/1.1\r\nHost: things.ubidots.com\r\n";
   }
      Serial.println("\n***********************************************************************************************************************\n");
   Serial.println("Getting your variable: \n");
   delay(2500);
   
   Flush();

   Serial.println("AT+CIPSTART=4,\"TCP\",\"things.ubidots.com\",80");
   delay(2500);
   
   Serial.println("AT+CIPSEND=4," + String(SEND));
   delay(500);

   Flush();
    
   Serial.println(GET);
   delay(1000);

   while (Serial.available()) {

     get_response = Serial.readString();
   }

   //  Serial.println(get_response);
   
   bodyPosinit = 4 + get_response.indexOf("\r\n\r\n");
   get_response = get_response.substring(bodyPosinit);

   bodyPosinit = 9 + get_response.indexOf("\"value\":");
   bodyPosend = get_response.indexOf("}]");
   get_response = get_response.substring(bodyPosinit,bodyPosend);

   Flush();
   
   //  Serial.println(get_response);
   
   num = get_response.toInt();

   return num;
}

void Flush() {

  byte w = 0;
  
  for (int i = 0; i < 10; i++) {
    
    while (Serial.available() > 0) {
          
      char k = Serial.read();
      w++;
      delay(1);
    }
    
    delay(1);
  }
}