ESP32 and C++ http post body

Hi,

I want to authorize my esp32 to shelly cloud. Every try ends up with 401.

I need to send my authorization data in POST BODY:

This is my code:

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>

String serverAddress = "shelly-20-eu.shelly.cloud";
int port = 443;
....
WiFiClient wifiClient;
    HttpClient http = HttpClient(wifiClient, serverAddress, port);;  
    http.setTimeout(5000);
    String postData = "id=someid&auth_key=someauthkey";
    String contentType = "application/x-www-form-urlencoded";

    http.beginRequest();
    http.post("/device/status", contentType, postData, root_ca);
    http.beginBody();
    http.print(postData);
    http.endRequest();

    int httpCode = http.responseStatusCode();
    String httpResponse = http.responseBody();

Any help with debuging would be great.

Is the postdata properly URL encoded?
Since you are providing it as a string, you’d need to take care of correct encoding there. Having that wrong might very well result in a 401.

Tried both:

String postData = "id=someid&auth_key=someauthkey";

or

String postData = "id%3Dsomeid%26auth_key%3Dsomeauthkey";

maybe I am encoding wrong ?

The first one is correct. The & and = characters are required in their original form.
The bits that need URL encoding are “someid” and “someauthkey”. I presume that those values are demo values and not real values, so I cannot tell if there are chars in there that need encoding.

I got it working :slight_smile: maybe not perfect but works :slight_smile:
I case someone needs this.

  1. ‘someid’ and ‘someauthkey’ are real data I did not want to put in open internet.
  2. The whole shelly cloud api integration is described here - https://shelly.cloud/documents/developers/shelly_cloud_api_access.pdf and this is where you can get ‘someid’ and ‘someauthkey’.

The code:

#include <WiFiClientSecure.h>
#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>

class GetWeather : public PollingComponent { 
 public:
  GetWeather() : PollingComponent(60000) {}
  Sensor *bed_hum = new Sensor();
  Sensor *bed_temp = new Sensor();

  const char* serverAddress = "shelly-20-eu.shelly.cloud";
  int port = 443;

  void setup() override {
    
  }

  void update() override {
    WiFiClientSecure wifiClient;
    wifiClient.setInsecure();
    HttpClient http = HttpClient(wifiClient, serverAddress, port);  
    http.setTimeout(5000);
    String postData = "id=someid&auth_key=someauthkey";
    String contentType = "application/x-www-form-urlencoded";

    http.beginRequest();
    http.post("/device/status", contentType, postData);
    http.beginBody();
    http.print(postData);
    http.endRequest();

    int httpCode = http.responseStatusCode();
    String httpResponse = http.responseBody();

    Serial.print("Shelly API http code: ");
    Serial.println(httpCode);

    // Comment out 2 next for json debug if http code was 200 success
    //Serial.print("Shelly response string: ");
    //Serial.println(httpResponse);

    if (httpCode > 0) {
      // Parsing
      const size_t bufferSize = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(8) + 370;
      DynamicJsonBuffer jsonBuffer(bufferSize);
      JsonObject& root = jsonBuffer.parseObject(httpResponse);
      
      float bed_hum_a = root["data"]["device_status"]["hum"]["value"];
      float bed_temp_a = root["data"]["device_status"]["tmp"]["value"];

      // Output
      Serial.print("Bedroom humidity: ");
      Serial.println(bed_hum_a);
      bed_hum->publish_state(bed_hum_a);

      Serial.print("Bedroom temperatur: ");
      Serial.println(bed_temp_a);
      bed_temp->publish_state(bed_temp_a);

    }
  }
};

So what was the magic bullet to get the auth part working? Adding the setInsecure call?

Well. If you don’t pass ssl you would not get 401 or 200 http response. I think you would end up with ssl error.

To be honest I think the problem was between keyboard and monitor :slight_smile: I just got some time today, cleaned the code, focused and got it working :slight_smile:

Yeah, no 401 should be returned in such case.
Well, good job getting it to work.
Mind that the solution was also between keyboard and chair :wink: