HTTPs REST-API mit dem ESP8266 abfragen
In einem anderem Tutorial habe ich bereits erklärt, wie man einfache HTTP GET-Requests mit einem ESP8266 ausführen und verarbeiten kann. Mit dieser Möglichkeit werden leider keine Anfragen an mit SSL verschlüsselte Verbindungen unterstützt. Aus diesem Grund möchte ich es zum Anlass nehmen, hier ein kurzes Tutorial darüber zu machen, die man eine REST API mit dem ESP8266 abfragen kann, auch wenn die Verbindung mit SSL verschlüsselt ist.
\nWichtig zu sagen ist: Die folgende Art und Weise ist nicht sicher, da wir ohne Fingerprint arbeiten und somit nur eine pseudo verschlüsselte Verbindung haben. Aber so können wir die Daten auslesen und verarbeiten.
\nDa wir mit einer REST API arbeiten, wäre es von Vorteil, wenn ihr euch mein Tutorial zum Thema Arduino IDE - Arbeiten mit JSON Objekten für Einsteiger anschauen würdet. Denn Ziel bei diesem Tutorial ist es, die Antwort des Servers ebenfalls als JSON behandeln zu können. Falls ihr nur schnell zum Ziel kommen wollt, reicht es die ArduinoJSON Library zu installieren.
\n\n
Der Endpoint
\nAls Endpoint der Anfrage verwenden wir eine Beispiel API von MisterT diese könnt ihr unter https://rip-my.dev/get/mistert abfragen:
\n{\n \"name\": \"MisterT\",\n \"description\": \"Wir stehen für eine gesunde Lebensweise. T \",\n \"ressources\": [\n \"/settings\",\n \"/stats\"\n ]\n}\n
\nIn dem Array ressources
stehen zusätzliche Endpunkte, die ihr callen könnt. Wir haben also insgesamt 3 REST-API Endpoints mit denen wir arbeiten können:
- \n
- https://rip-my.dev/get/mistert \n
- https://rip-my.dev/get/mistert/settings \n
- https://rip-my.dev/get/mistert/stats \n
Ich entscheide mich für dieses Tutorial für den zweiten Endpoint, da wir dort am meisten Daten zum Testen haben.
\nDer Code
\nAls Grundlage verwende ich den Code aus meinem Tutorial ESP8266 HTTP-GET Request. Der einzige Unterschied ist, dass wir mit dem folgenden zwei Code-Anpassungen auch auf HTTPs Endpoints zugreifen können:
\nWiFiClient wifiClient;
wird zu: WiFiClientSecure wifiClient;
Zusätzlich, da wir ohne Fingerprint arbeiten, setzen wir den Client dann vor der eigentlichen REST-Abfrage auf insecure:
\nwifiClient.setInsecure();\n
\nUnd schon kann eine GET-Request an einen HTTPs-Server gesendet werden.
\n/*\n HTTPS REST-API GET\n Basic-Code für GET-Request an einen HTTPS-Server\n Created by cooper, 2020\n makesmart.net\n*/\n \n#include <ESP8266WiFi.h>\n#include <ESP8266HTTPClient.h>\n \nHTTPClient sender;\nWiFiClientSecure wifiClient;\n \n// WLAN-Daten\nconst char* ssid = \"WLAN-SSID\";\nconst char* password = \"WLAN-PSK\";\n \n \nvoid setup() {\n Serial.begin(115200);\n \n WiFi.begin(ssid, password);\n \n while (WiFi.status() != WL_CONNECTED) {\n delay(200);\n Serial.print(\".\");\n }\n \n Serial.println(\"Mit dem WLAN verbunden!\");\n Serial.println();\n \n wifiClient.setInsecure();\n if (sender.begin(wifiClient, \"https://rip-my.dev/get/mistert/settings\")) {\n // HTTP-Code der Response speichern\n int httpCode = sender.GET(); \n if (httpCode > 0) {\n // Anfrage wurde gesendet und Server hat geantwortet\n // Info: Der HTTP-Code für 'OK' ist 200\n if (httpCode == 200) {\n // Hier wurden die Daten vom Server empfangen\n // String vom Webseiteninhalt speichern\n String payload = sender.getString();\n // Hier kann mit dem Wert weitergearbeitet werden\n // ist aber nicht unbedingt notwendig\n Serial.println(payload);\n }else{\n // Falls HTTP-Error\n Serial.print(\"HTTP-Error: \" + String(httpCode));\n }\n }\n // Wenn alles abgeschlossen ist, wird die Verbindung wieder beendet\n sender.end();\n }else {\n Serial.printf(\"HTTP-Verbindung konnte nicht hergestellt werden!\");\n }\n \n}\n \n \nvoid loop() {\n \n}\n
\nDas ist mal eine Standard-HTTPs Anfrage an den definierten Server https://rip-my.dev/get/mistert/settings. Als Rückgabewert erhalten wir im seriellen Monitor das JSON Objekt als einfachen String:
\n{\"adress\":\"192.168.178.27\",\"name\":\"MisterT\",\"default_fill_ml\":220,\"water_value\":4.2,\"additive_value\":10.6,\"standby_color\":\"#fff\",\"strength\":1,\"api_enabled\":true}\n
\nDiese Response möchten wir jetzt als JSON verarbeiten um sehr leicht auf die einzelnen Keys und Values zugreifen zu können. Das geht wie bereits erwähnt am einfachsten mit der ArduinoJSON Library.
\nArbeiten mit der Response als JSON
\nZuerst müssen wir in unserem Programm die Arduino JSON Library einbinden:
\n#include <ArduinoJson.h>
Die ganze restliche Magie passiert dann, nachdem wir die Antwort vom Server erhalten haben.
\nDas JSON-Objekt wird im Code bereits als Variable payload
gespeichert, dass passiert in der folgenden Zeile:
if (httpCode == 200) {\n // Hier wurden die Daten vom Server empfangen\n // String vom Webseiteninhalt speichern\n String payload = sender.getString();\n // Hier kann mit dem Wert weitergearbeitet werden\n // ist aber nicht unbedingt notwendig\n Serial.println(payload);\n }\n
\n{\n \"adress\": \"192.168.178.27\",\n \"name\": \"MisterT\",\n \"default_fill_ml\": 220,\n \"water_value\": 4.2,\n \"additive_value\": 10.6,\n \"standby_color\": \"#fff\",\n \"strength\": 1,\n \"api_enabled\": true\n}\n
\nDie Variable payload
kann direkt dafür verwendet werden das JSON Objekt zu deserialisieren.
if (httpCode == 200) {\n // Hier wurden die Daten vom Server empfangen\n // String vom Webseiteninhalt speichern\n String payload = sender.getString();\n\n // Hier wird ein neuer Buffer mit dem Namen response erzeugt, mit dem wir an die Werte kommen\n DynamicJsonDocument response(1024);\n DeserializationError error = deserializeJson(response, payload);\n if (error)\n return;\n \n // Hier lesen wir die Werte über den Buffer aus\n String myName = response[\"name\"];\n int default_fill_ml = response[\"default_fill_ml\"];\n bool api_enabled = response[\"api_enabled\"];\n String standby_color = response[\"standby_color\"];\n\n // Einfache Ausgabe über den seriellen Monitor\n Serial.println(myName);\n Serial.println(default_fill_ml);\n Serial.println(api_enabled);\n Serial.println(standby_color);\n \n}\n
\nMisterT\n220\n1\n#fff\n
\nSo einfach ist, es eine REST API mit dem ESP8266 abzufragen. Wenn du dich mehr für das Thema ArduinoJSON interessierst, dann lohnt sich wie gesagt ein Blick in mein Tutorial Arduino IDE - Arbeiten mit JSON Objekten für Einsteiger. Und für alle die auf der Suche nach einer Copy & Paste Lösung sind, hier nochmal der komplette Code für das deserialisiereneiner REST-API Antwort:
\n/*\n HTTPS REST-API GET\n Basic-Code für GET-Request an einen HTTPS-Server\n Created by cooper, 2020\n makesmart.net\n*/\n \n#include <ESP8266WiFi.h>\n#include <ESP8266HTTPClient.h>\n \nHTTPClient sender;\nWiFiClientSecure wifiClient;\n\n#include <ArduinoJson.h>\n \n// WLAN-Daten\nconst char* ssid = \"WLAN-SSID\";\nconst char* password = \"WLAN-PSK\";\n \n \nvoid setup() {\n Serial.begin(115200);\n \n WiFi.begin(ssid, password);\n \n while (WiFi.status() != WL_CONNECTED) {\n delay(200);\n Serial.print(\".\");\n }\n \n Serial.println(\"Mit dem WLAN verbunden!\");\n Serial.println();\n \n wifiClient.setInsecure();\n if (sender.begin(wifiClient, \"https://rip-my.dev/get/mistert/settings\")) {\n // HTTP-Code der Response speichern\n int httpCode = sender.GET(); \n if (httpCode > 0) {\n // Anfrage wurde gesendet und Server hat geantwortet\n // Info: Der HTTP-Code für 'OK' ist 200\n if (httpCode == 200) {\n // Hier wurden die Daten vom Server empfangen\n // String vom Webseiteninhalt speichern\n String payload = sender.getString();\n\n // Hier wird ein neuer Buffer mit dem Namen response erzeugt, mit dem wir an die Werte kommen\n DynamicJsonDocument response(1024);\n DeserializationError error = deserializeJson(response, payload);\n if (error)\n return;\n \n // Hier lesen wir die Werte über den Buffer aus\n String myName = response[\"name\"];\n int default_fill_ml = response[\"default_fill_ml\"];\n bool api_enabled = response[\"api_enabled\"];\n String standby_color = response[\"standby_color\"];\n\n // Einfache Ausgabe über den seriellen Monitor\n Serial.println(myName);\n Serial.println(default_fill_ml);\n Serial.println(api_enabled);\n Serial.println(standby_color);\n \n }else{\n // Falls HTTP-Error\n Serial.print(\"HTTP-Error: \" + String(httpCode));\n }\n }\n // Wenn alles abgeschlossen ist, wird die Verbindung wieder beendet\n sender.end();\n }else {\n Serial.printf(\"HTTP-Verbindung konnte nicht hergestellt werden!\");\n }\n \n}\n \n \nvoid loop() {\n \n}\n