0

I'm new to esp32 and now I'm trying to Get data using ArduinoJson, In my googlesheet "A1" have a number and I want to let esp32 to get it, I send my googlesheet to internet and use the url:https://spreadsheets.google.com/feeds/cells/1RICYSv0y0wEEu-PhcCL45jZmh7DlFSAsbW8Bie0inbA/1/public/values?alt=json&range=A1. and my number is at object > feed > entry > 0 > content > $t.

Here's a problem:When I use esp32 to get this json data,I can't get it,even my esp32 connected to googlesheet

Here is my full code if you need:

#include <ArduinoJson.h>
#include <WiFi.h>
#include <SPI.h>

WiFiClient client;

const char* ssid = "wwwwwwwww";
const char* password = "wwwwwwww";
const char* server = "spreadsheets.google.com";
const char* resource = "/feeds/cells/1RICYSv0y0wEEu-PhcCL45jZmh7DlFSAsbW8Bie0inbA/1/public/values?alt=json&range=A1";


const unsigned long HTTP_TIMEOUT = 10000;  // max respone time from server
const size_t MAX_CONTENT_SIZE = 1024;       // max size of the HTTP response

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

struct clientData {
  char item[8];
};


void setup() {
  Serial.begin(9600);
  while (!Serial) {

  }
  Serial.println("Serial ready");
  Serial.print("Connecting to wifi: ");
  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());
}


void loop() {
  if(connect(server)) {
    if(sendRequest(server, resource) && skipResponseHeaders()) {
      clientData clientData;
      if(readReponseContent(&clientData)) {
        printclientData(&clientData);
      }
    }
  }
  disconnect();
  wait();
}


bool connect(const char* hostName) {
  Serial.print("Connect to ");
  Serial.println(hostName);

  bool ok = client.connect(hostName, 80);

  Serial.println(ok ? "Connected" : "Connection Failed!");
  return ok;
}


bool sendRequest(const char* host, const char* resource) {
  Serial.print("GET ");
  Serial.println(resource);

  client.print("GET ");
  client.print(resource);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(host);
  client.println("Connection: close");
  client.println();

  return true;
}

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;
}


bool readReponseContent(struct clientData* clientData) {
  const size_t bufferSize = 5*JSON_ARRAY_SIZE(1) + 
  JSON_ARRAY_SIZE(5) + 10*JSON_OBJECT_SIZE(1) + 
  6*JSON_OBJECT_SIZE(2) + 7*JSON_OBJECT_SIZE(3) + 
  JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(7) + JSON_OBJECT_SIZE(15);
  DynamicJsonBuffer jsonBuffer(bufferSize);

  JsonObject& root = jsonBuffer.parseObject(client);

  if (!root.success()) {
    Serial.println("JSON parsing failed!");
    return false;
  }

  strcpy(clientData->item, root["feed"]["entry"][0]["content"]["$t"]);

  return true;
}


void printclientData(const struct clientData* clientData) {
  Serial.print("Time = ");
  Serial.println(clientData->item);

}

void disconnect() {
  Serial.println("Disconnect");
  client.stop();
}

void wait() {
  Serial.println("Wait 20 seconds");
  delay(20000);
}

Serial Output:

Connecting to wifi: wwwwwwwwww
..
WiFi connected
IP address: 
xxx.xxx.x.xx
Connect to spreadsheets.google.com
Connected
GET /feeds/cells/1RICYSv0y0wEEu-PhcCL45jZmh7DlFSAsbW8Bie0inbA/1/public/values?alt=json&range=A1
JSON parsing failed!
Disconnect
Wait 20 seconds

  • What is your version of ArduinoJson? your code is based on ArduinoJson v5, if you are running v6, see [migrate from version 5 to 6](https://arduinojson.org/v6/doc/upgrade/) documentation. – hcheung Feb 17 '20 at 14:03
  • @hcheung I use version 5 because I didn't quite know how to use version 6 at all – NekoshimaTama Feb 17 '20 at 15:49
  • 1
    If I were debugging this I would store the value being returned by the client in a String, output that String and then attempt to parse it. As it is you have no idea what you're actually passing to `parseObject()`. The first step would be to confirm that you actually downloaded what you thought you downloaded and that it is actually valid JSON. – romkey Feb 17 '20 at 16:57
  • @romkey i don't really know how to get a value from client i tried Serial.println(client) and client.read(); but its both output 1 – NekoshimaTama Feb 18 '20 at 10:54

1 Answers1

0

If I based on your json output and calculate the bufferSize using ArduinoJson Assistant, I get this:

const size_t capacity = 5*JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(5) + 10*JSON_OBJECT_SIZE(1) + 6*JSON_OBJECT_SIZE(2) + 7*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(7) + JSON_OBJECT_SIZE(15) + 2270;

Noticed the + 2270 at the end? Your parsing json failed because your are short of 2270 bytes in bufferSize (i.e. your bufferSize is too small).

Updte

I didn't try to debug your code, but I have my web client code handy with me so I just run and it works for me.

My code is based on HTTPClient which is part of ESP32 Arduino Core that you can further read about it at ESP-Arduino github. It is based on Arduino WifiClient that you used but with much simpler and easy to use API, especially for getting response payload. I would recommend you take a look.

I add ArduinoJson to my code to see if there is any issue on parsing the received json, but mines is based on v6 syntax, you can convert it to v5 syntax if you still feel it is easier for you to use v5. BTW, the json document contains Unicode, I have to add #define ARDUINOJSON_DECODE_UNICODE 1 on the top of the program in oder to make it work, otherwise I will get an deserialization error: NotSupported.

#define ARDUINOJSON_DECODE_UNICODE 1
#include <ArduinoJson.h>
#include <WiFi.h>
#include <HTTPClient.h>

HTTPClient http;

const char* ssid = "your_SSID";
const char* password = "your_password";

const char* url = "https://spreadsheets.google.com/feeds/cells/1RICYSv0y0wEEu-PhcCL45jZmh7DlFSAsbW8Bie0inbA/1/public/values?alt=json&range=A1";

void setup() {
  Serial.begin(115200);
  while (!Serial) {}

  Serial.print("Connecting to wifi: "); Serial.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("IP address: "); Serial.println(WiFi.localIP());

  http.begin(url); 
  int httpCode = http.GET();  //send GET request

  if (httpCode != 200) {
    Serial.print("Error on HTTP request: ");
    Serial.println(httpCode);
  } else {
    String payload = http.getString();
    Serial.println(payload);

    // the following is based on ArduinoJson v6 API
    StaticJsonDocument<4000> doc;
    DeserializationError err = deserializeJson(doc, payload);
    if (err) {
      Serial.print("deserialization error ");
      Serial.println(err.c_str());
    }

    JsonObject feed = doc["feed"];
    const char* clientData = feed["entry"][0]["content"]["$t"];
    Serial.println(clientData);
  }

  http.end(); //Free the resources

}


void loop() {

}
hcheung
  • 3,377
  • 3
  • 11
  • 23
  • I tried to use ArduinoJson Assistant again and I get 2260 bytes this time so I change it and it still failed again even I change to 10000 bytes – NekoshimaTama Feb 18 '20 at 06:01
  • maybe you shouldn't skipResponseHeader, but to find out what get send back from the server first then. – hcheung Feb 18 '20 at 15:07
  • It's seems esp32 didn't get anything from client, when I client.read() it I can only get "1" when I print to serial, but I dont know why it connected to the host but esp32 not getting the things – NekoshimaTama Feb 19 '20 at 07:47
  • I run a simple web client sketch (not your sketch) to access the google spreadsheet and I have not problem in getting the response back. To be honest, your code have too many unnecessary functions that aren't necessary, e.g. you declare server as a global variable, it make no sense to pass it in as parameter in connect() function, write simple code and it much easier to see what's going on. – hcheung Feb 20 '20 at 01:31
  • `client.read()` read one byte at a time. Uses `if (client.available()>0) {String line=client.readStringUntil('\r'); Serial.print(line);}` to see the response result. – hcheung Feb 20 '20 at 01:34
  • HTTP/1.1 200 OK that is what it response, and yeah I know it have lack of unnecessary function ,but I want to fix this problem first – NekoshimaTama Feb 20 '20 at 08:42
  • Well, not sure how you did, you get the correct status code back but you either didn't get the payload or you didn't read the payload. I mentioned that my web client works, I have updated my answer and post my code. – hcheung Feb 21 '20 at 00:05
  • after doing the convert to the ArduinoJson v5 and yeah! It's working perfectly with no bugs! thanks @hcheung ,you are truly a life saver! now I can finally move on to make this better! – NekoshimaTama Feb 21 '20 at 08:51