pstryk
April 30, 2021, 7:56pm
1
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.
mmakaay
(Maurice Makaay)
April 30, 2021, 11:11pm
2
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 ?
mmakaay
(Maurice Makaay)
May 1, 2021, 7:03am
4
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 maybe not perfect but works
I case someone needs this.
‘someid’ and ‘someauthkey’ are real data I did not want to put in open internet.
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);
}
}
};
mmakaay
(Maurice Makaay)
May 2, 2021, 8:54pm
6
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 I just got some time today, cleaned the code, focused and got it working
mmakaay
(Maurice Makaay)
May 2, 2021, 9:05pm
8
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