Rafik73
Rafik73

Reputation: 51

arduino ide esp8266 json decode from URL

I program esp8266 using the Arduino IDE. I join with the local network via WIFI. Ultimately, I want to download content JSON generated on the local server. I am using the code:

 #include <ESP8266WiFi.h>
    #include <ArduinoJson.h>

    const char* ssid     = "NeoRaf";
    const char* password = "password";
    const char* host = "192.168.1.8";

    void setup() {
      Serial.begin(115200);
      delay(100);

      // We start by connecting to a WiFi network

      Serial.println();
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);

      WiFi.begin(ssid, password);

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

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

      //-----------------------
      delay(5000);

      Serial.print("connecting to ");
      Serial.println(host);

      // Use WiFiClient class to create TCP connections
      WiFiClient client;
      const int httpPort = 8095;
      if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
      }

      // We now create a URI for the request
      String url = "/api";
      Serial.print("Requesting URL: ");
      Serial.println(url);

      // This will send the request to the server
      client.print("GET " + url + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "ApiCode: 8273\r\n" +
                   "Content-Type: application/json\r\n" + 
                   "Connection: close\r\n\r\n");
      delay(500);
       char c[1024];
      // Read all the lines of the reply from server and print them to Serial
       while(client.available()){
          c[0] = client.read();

      //Serial.print(c);

     Serial.print(c);
     }
       StaticJsonBuffer<200> jsonBuffer;
       JsonObject& root = jsonBuffer.parseObject(c);
      int data = root["lowVersion"];  
      Serial.println();
         Serial.print(data);

      Serial.println();
      Serial.println("closing connection");  
    }

    void loop()
    {}

The result is this:

    Connecting to NeoRaf
    ......
    WiFi connected
    IP address: 
    192.168.1.21
    connecting to 192.168.1.8
    Requesting URL: /api
    HTTP/1.1 200 OK
    Content-Length: 32
    Content-Type: application/json
    Server: Microsoft-HTTPAPI/2.0
    Access-Control-Allow-Origin: *
    Date: Mon, 06 Jun 2016 16:50:48 GMT
    Connection: close

{"lowVersion":1,"highVersion":3}
0
closing connection

This line is JSON:

{"lowVersion":1,"highVersion":3}

So it should display 1 and displays 0. I do not know how to get rid of the header:

HTTP/1.1 200 OK
Content-Length: 32
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
Access-Control-Allow-Origin: *
Date: Mon, 06 Jun 2016 16:50:48 GMT

and how to read the contents of JSON ( lowVersion or highVersion)?

Upvotes: 1

Views: 10695

Answers (3)

Benoit Blanchon
Benoit Blanchon

Reputation: 14511

HTTP headers always end with an empty line, so you just need to read until you find two consecutive line breaks.

Have a look at ArduinoJson's example JsonHttpClient.ino, it uses Stream::find():

// Skip HTTP headers so that we are at the beginning of the response's body
bool skipResponseHeaders() {
  // HTTP headers end with an empty line
  char endOfHeaders[] = "\r\n\r\n";

  client.setTimeout(HTTP_TIMEOUT);
  bool ok = client.find(endOfHeaders);

  if (!ok) {
    Serial.println("No response or invalid response!");
  }

  return ok;
}

Upvotes: 1

Hashin
Hashin

Reputation: 3

First of all, for handling HTTP requests, you can use a RestClient library rather than writing all the low level requests. It saves a lot of time and is less error-prone.

For example, for a GET request, all you have to do is:

String response = "";
int statusCode = client.get("/", &response);

One good such library with SSL support is written by github user DaKaz.

You can use it for your GET request. The returned response will be without the HTTP header. The function will return the response from the server without the headers.

Now you can use the ArduinoJson Library by bblanchin for decoding the JSON object.

Details can be seen here.

Or you can do plain string manipuation to get the values though it is not a recommended route to take and is prone to errors.

Upvotes: 0

Marcel St&#246;r
Marcel St&#246;r

Reputation: 23525

You need to detect when the payload starts in the HTTP response. So, when you read data from the client you can skip all HTTP header lines. Incidentally in a JSON response the first { usually signifies the start of the JSON document.

httpbin example

Requesting http://httpbin.org/get yields

{
  "args": {}, 
  "headers": {
    ...
  }, 
  "origin": "XXXXXXX", 
  "url": "http://httpbin.org/get"
}

You can print the "url" field like so:

String json = "";
boolean httpBody = false;
while (client.available()) {
  String line = client.readStringUntil('\r');
  if (!httpBody && line.charAt(1) == '{') {
    httpBody = true;
  }
  if (httpBody) {
    json += line;
  }
}
StaticJsonBuffer<400> jsonBuffer;
Serial.println("Got data:");
Serial.println(json);
JsonObject& root = jsonBuffer.parseObject(json);
String data = root["url"];

Upvotes: 1

Related Questions