Search code examples
jsonarduinoesp8266

Issues posting a JSON object to a server from an ESP8266 Arduino board


I am trying to post a JSON object to a server deployed on Heroku from an ESP8266 board.

My problem is that I am not posting anything or I am posting a wrong JSON object, as Heroku logs show a 500 error and I am getting an empty object on the serial monitor.

My understanding is that I am hitting the server correctly, but either the format of the JSON object is wrong or I am missing something in my post method.

Could you please check my code and help me find a solution?

Here is my code:

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h> 
#include <WiFiClient.h> 

const char *host = "appname.herokuapp.com";
const char* serverName = "https://appname.herokuapp.com";
const char* ssid = "*******"; 
const char* password = "*******";

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

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {

  if(WiFi.status()== WL_CONNECTED) {
      std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
      client->setInsecure();
     
      HTTPClient https;

      DynamicJsonDocument doc(512);
      JsonObject object = doc.to<JsonObject>();
      object["temperature"] = 30;
      String data;
      serializeJsonPretty(object, data);

      Serial.println(data);

      https.addHeader("Accept:", "application/json");
      https.addHeader("Host:", host);

      if (https.begin(*client, serverName)) {
          Serial.print("[HTTPS] POST...\n");
          int httpCode = https.POST(data);

          if (httpCode > 0) {
            Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
            
            if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
              String payload = https.getString();
              Serial.println(payload);

            } else {
              Serial.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
            }

          } else  {
            Serial.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
          }
          https.end();

    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    } 
  }
  delay(5000);
}

Solution

  • The problem was to have the post method nested inside the if statement instead of having it after adding the headers. I have modified the code and now it works.

    void loop() {
    
      if(WiFi.status()== WL_CONNECTED) {
    
        std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
        client->setInsecure();
     
        HTTPClient https;
    
        DynamicJsonDocument doc(512);
        JsonObject object = doc.to<JsonObject>();
          
        object["temperature"] = 32;
    
        String data;
        serializeJsonPretty(object, data);
    
        Serial.println(data);
    
        https.begin(*client, serverName);
        https.addHeader("Content-Type", "application/json; charset=UTF-8");       
          
        int httpCode = https.POST(data);
    
        if (httpCode == 200) {
          Serial.println("POST succeeded with code:");
          Serial.println(httpCode);
          
        } else if (httpCode != 200) {
          Serial.println("POST failed with code:");
          Serial.println(httpCode);
    
        } else {
          Serial.println("Unknown error");
        }
    
        String payload = https.getString();
        Serial.println(payload);
    
        https.end();
      }
      delay(10000);
    }