Auslesen eines Google Kalenders

Hallo,

ich versuche seid geraumer Zeit über einen http POST request an die Events meines Kalenders zu kommen. Ich möchte ein Raumbelegungsdisplay mittels ESP32 bauen. Dazu wird ein Kalender angelegt, in welchem ein Termin eingetragen wird. Auf dem Display am Raum soll dann stehen, von wann bis wann der Raum frei bzw belegt ist. Dies soll dann auf mehrere Räume erweitert werden.

Google beschreibt es wie folgt. Zunächst muss man ein POST request senden, um ein Zugriff auf die API zu erlangen. Mit Hilfe des empfangenen Codes sendet man einen erneuten POST request um den Access Token zu bekommen. Mit diesem Token und ein paar weiteren Parametern erlangt man dann die Infos aus dem Kalender.

Ich habe mit Matlab bereits erfolgreich meine Kalender auslesen können. Heißt, dass das soweit gehen müsste.

Bei der Umsetzung im ESP32 scheiterts aber schon am ersten POST request. Laut google sollt dieser wie folgt aussehen:

POST /o/oauth2/device/code HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&
scope=APIscope

Ich habe es über zwei Varianten probiert. Einmal mittels HTTPclient aus der ESP32-Library:

void getGoogleAPIaccessHTTP()
  {
  Serial.println("start HTTP function");
  
  HTTPClient http;

  String host = "https://accounts.google.com";
  String url  = "/o/oauth2/device/code";

  String postCode = ("client_id=" + ClientID + "&scope=" + CalenderScope);
  
  http.begin(host + url);
  http.addHeader("Host", "accounts.google.com", "Content-Type", "application/x-www-form-urlencoded");
  
  Serial.println("Request URI");
  Serial.println(postCode);

  int httpResponseCode = http.POST(postCode);

  if (httpResponseCode > 0)
    {
    String payload = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(payload);
    String response = http.getString();                       //Get the response to the request
    Serial.println(response);                                 //Print request answer
    }

    delay(2000);
    
  http.end();  //Free resources
  }

als Antwort erhalte ich:

{
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unexpected token.\nclient_id=1234567890\n^",
    "status": "INVALID_ARGUMENT"
  }
}

wobei hier genau 10 Stellen der ClientID zurückgegeben werden. Diese ist jedoch 72 Stellen groß.

Mein zweiter Versuch war es den WiFiClientSecure zu nutzen (hier gleich vorweggenommen, auch der WiFiClient führte nicht zum Erfolg):

void getGoogleAPIaccessWS()
  {
  Serial.println("start WiFi-http function");
  WiFiClientSecure wsclient;
  
  String postString = (String("POST ") + "/o/oauth2/device/code" + " HTTP/1.1\r\n" +
             "Host: accounts.google.com\r\n" +
             "Content-Type: application/x-www-form-urlencoded\r\n\r\n"+
             "client_id=" + ClientID + "&\r\n" + "scope=" + CalenderScope +"\r\n");

  if (wsclient.connect("accounts.google.com/o/oauth2/device/code",443));
  //if (wsclient.connect("https://accounts.google.com/o/oauth2/device/code",443));
  //if (wsclient.connect("accounts.google.com",443));
  //if (wsclient.connect("https://accounts.google.com",443));
    {
    Serial.println("connected");
    Serial.println("Request URI");
    Serial.println(postString);
    wsclient.print(postString);
    
    delay(1000);
    }

  if (wsclient.available())
    {
    Serial.println("Data available");

    int line = wsclient.readStringUntil('\r');
    Serial.println("received string:");
    Serial.println(line);
    }

  wsclient.stop();  //Free resources

}

Ergebnis hier, wsclient.available() wird nie true.

Kann mir hier irgendjemand den entscheidenden Tipp oder Hinweis geben, was ich falsch mache?

Vielen Dank.

Thomas

Hi,
verwende bitte die Code-Tags < / > dann kann man den Code deutlich einfacher lesen.

Dein Problem mit der Lösung 1 ist doch in der Meldung exakt beschrieben!
Es konnte in den Daten kein gültiges json mit den Anmeldeinformationen gefunden werden.

Warum? Weil Du kein gültiges Json im Body übergibst :slight_smile:

Was Du da in der Variablen postCode zusammenbaust sind Parameter. Diese werden der URL einfach angefügt:

google.de?login=123&password=4711

Das probierst Du aber gerade in den Body zu schreiben.

Was Du benötigst ist ein Body mit den Werten ala

{
   "login":"123",
   "password":"4711"
}

Dann solltest Du auch den ContentType auf json/text anpassen.

Hallo,

Danke für die schnelle Antwort. Das werde ich mal testen, jedoch widerspricht das aber der Guideline der GoogleApi. Da steht ja explizit:

POST /o/oauth2/device/code HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&
scope=APIscope

also Host und Content-Type im Header bzw. client_id und scope im Body. Dass ich ein JSON format senden muss, steht nirgendwo in der Guideline.