APIs und Daten: Wie viele Menschen sind im Weltall?

Jetzt, wo du mit deinem ESP8266 mit dem Internet verbinden kannst, wird es Zeit für Daten. In dieser Lektion lernst du, wie du Daten im JSON-Format lädst und mithilfe der Bibliothek ArduinoJson dekodierst (oder parst).

Hierfür wirst du eine API kontaktieren und JSON-Daten herunterladen, die die aktuelle Anzahl von Menschen im Weltraum enthalten. Diese Daten wirst du auf deinem ESP8266 parsen und das Ergebnis in deinem Seriellen Monitor anzeigen. JSON ist ein Datenformat, das mittlerweile überall Anwendung findet. Bei Wikipedia findest du viele weitere Informationen – aber auch im Verlauf der nächsten Lektionen wirst du viel über JSON lernen.

Die Bibliothek ArduinoJson

Bevor du loslegen kannst, benötigst du die aktuelle Version der Bibliothek ArduinoJson. Hierbei handelt es sich um eine wirklich praktische Erweiterung, die dir die meiste Arbeit mit JSON abnimmt.

Öffne also deinen Bibliotheksverwalter in der Arduino IDE und suche dort nach ArduinoJson. Installiere dir die neueste Version.

Lass dich nicht von der Versionsnummer verwirren – diese wird bei dir schon höher sein.

Sobald die Bibliothek installiert ist, kannst du sie in deinem Sketch einbinden. Erstelle zunächst einen neuen Sketch und kopiere folgende Zeile in die erste Zeile (noch vor der Setup-Funktion):

#include <ArduinoJson.h>

Der API Call

Um herauszufinden, wie viele Astronauten gerade im Weltall sind, fragen wir eine API von open-notify.org ab – und zwar unter folgender URL:

  http://api.open-notify.org/astros.json

Wenn du diese URL kopierst und in deinem Browser öffnest, siehst du bereits die Rohdaten im JSON-Format. Recht am Anfang findest du “number” und dahinter die aktuelle Anzahl Astronauten im Weltraum. Heute – am 6. Februar 2021 – sind das 7.

Dahinter findest du weitere Informationen zu den einzelnen Astronauten – ihren Namen und wo sie sich gerade befinden.

Bevor du loslegen kannst, musst du deinen ESP8266 mit dem Internet verbinden. Binde also zunächst wieder die entsprechende Bibliothek und deine Zugangsdaten zu Beginn deines Sketchs ein:

#include <ESP8266WiFi.h>

const char* ssid = "Name deines WLAN-Netzwerks";
const char* password =  "Dein WLAN-Passwort";

Außerdem benötigst du noch eine weitere Bibliothek für den API Call – ESP8266HTTPClient.h

Diese musst du nicht eigens installieren, da sie nach der Installation des ESP8266 in der Arduino IDE verfügbar ist. Binde auch diese Bibliothek zu Beginn hinter den anderen Bibliotheken ein:

#include <ESP8266HTTPClient.h>

Die Setup-Funktion

In der Setup-Funktion folgt dann der Code, um deinen ESP8266 mit deinem WLAN zu verbinden:

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Ich verbinde mich mit dem Internet...");
  }
  Serial.println("Ich bin mit dem Internet verbunden!");
}

Wie du siehst, startest du dort darüber hinaus noch deinen Seriellen Monitor mit der folgenden Zeile. Die Baudrate kannst du natürlich selbst wählen.

Serial.begin(115200);

Der Loop

Jetzt hast du alle Vorbereitungen im Sketch getroffen und kannst nun die Daten von der API abrufen – das machst du im Loop.

Hier prüfst du jedoch zunächst einmal, ob der ESP8266 tatsächlich mit dem Internet verbunden ist:

if ((WiFi.status() == WL_CONNECTED)) {

Wenn das der Fall ist, kannst du die Abfrage starten:

HTTPClient http;
http.begin("http://api.open-notify.org/astros.json");
int httpCode = http.GET();

In der ersten Zeile erstellst du zunächst eine Instanz der Bibliothek ESP8266HTTPClient.h mit dem Namen http.

Danach folgt die Abfrage an der oben genannten URL. Wenn du diese Adresse im Browser öffnest, siehst du – sofern sie erreichbar ist – einfach die Daten. Im Hintergrund sendet der entsprechende Server jedoch einen Code. Wenn der Server erreichbar ist und deine Anfrage annehmen kann, ist das der Code 200.

Nur in diesem Fall, erhältst du also die Daten, die du möchtest. Deshalb speicherst du in der dritten Zeile diesen Code zunächst in der Variablen httpCode. Anschließend erstellst du eine weitere Abfrage, die den nachfolgenden Code nur ausführt, wenn dein ESP8266 vom Server den Code 200 erhalten hat:

if (httpCode == 200) {

Die Daten erhältst du vom Server mit der Funktion http.getString() und speicherst sie in der Variablen input:

String input = http.getString();

Jetzt befinden sich hierin die Rohdaten, die du von der API geladen hast – und zwar im JSON-Format. Das ist im Prinzip genau die Zeichenkette, die du auch im Browser gesehen hast.

Schön und gut, aber um diese Daten weiterverarbeiten zu können – also z.B. die aktuelle Anzahl Astronauten zu erhalten – musst du sie zunächst dekodieren bzw. parsen. Und hier kommt die Bibliothek ArduinoJson ins Spiel.

Parsen mit ArduinoJson

Mit dieser Bibliothek greifst du dir einzelne Daten aus dem JSON-String und speicherst sie in Variablen deiner Wahl. Damit sie jedoch ihre Arbeit erledigen kann, muss sie zunächst wissen, wie groß die Rohdaten sind, um sich selbst genügend Arbeitsspeicher auf dem ESP8266 zu reservieren.

Hierfür gibt es einen praktischen Assistenten. Öffne zunächst noch einmal die URL der API und kopiere dir mit Strg + A und Strg + C sämtliche Zeichen.

Öffne anschließend den Assistenten von ArduinoJson – hier erwartet dich eine Art Wizard. Wähle im ersten Schritt die folgenden Einstellungen und klicke auf Next: JSON.

ArduinoJson Assistant Schritt 1

Kopiere im nächsten Schritt den JSON-String aus deinem Browser in das Textfeld und klicke dich durch zum nächsten Schritt.

In Schritt 3 erhältst du Informationen über die Größe der Daten, die du jedoch an dieser Stelle nicht weiter beachten musst. Je größer der JSON-String, desto größer auch der Speicher, den die Bibliothek zum Parsen benötigt. Gehe weiter zu Schritt 4.

Hier wird es jetzt interessant, denn du erhältst hier bereits den Code, den du in deinem Sketch benötigst.

Zunächst die erwähnte Speichergröße. In unserem Fall sind das 768 Bytes. Bei dir können es jedoch mehr oder weniger sein – je mehr Astronauten im Weltall sind, desto größer dein Speicherbedarf. 🙂

Trage die ersten beiden Zeilen nun in deinen Sketch ein – direkt unter der Zeile, in der du die Daten in die Variable input gespeichert hast.

StaticJsonDocument<768> doc;
deserializeJson(doc, input);

Die erste reserviert den benötigten Speicher und die zweite kümmert sich dann schon um das Dekodieren der Daten.

Um die Zahl der Menschen im Weltall nun herauszufinden, ist nur eine weitere Zeile Code nötig:

int number = doc["number"];

Hier speicherst du in der Variablen number den Wert aus dem Key-Value-Paar “number”: 7 im JSON-String. Der Key, den du in der oberen Zeile aufrufst lautet “number” – und der hier hinterlegte Wert (Value) 7. Beachte wieder: Der Wert kann bei dir anders lauten.

Jetzt musst du nur noch den Inhalt der Variablen number im Seriellen Monitor ausgeben:

Serial.println(number);

Und das war es auch schon! In deinem Seriellen Monitor sollte nun die Zahl der Astronauten im Weltall erscheinen.

Noch ein paar Hinweise: Wenn du die Abfrage nur einmal beim Start des ESP8266 ausführen möchtest, kannst du den gesamten Inhalt des Loops auch im Setup ausführen. Die Funktion void loop() bleibt dann einfach leer.

Wenn du allerdings den Loop nutzt – so wie wir in dieser Lektion – füge am Ende noch einen delay ein. Ansonsten würde dein ESP8266 eine Abfrage nach der anderen an die API starten. Das wäre völlig unnötig, denn wie du weißt, brechen Menschen nicht wirklich häufig ins Weltall auf, weswegen ihre Anzahl dort relativ konstant bleibt. 😉

Hier nun der gesamte Sketch:

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

const char* ssid = "Name deines WLAN-Netzwerks";
const char* password =  "Dein WLAN-Passwort";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Ich verbinde mich mit dem Internet...");
  }
  Serial.println("Ich bin mit dem Internet verbunden!");
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {
    HTTPClient http;
    http.begin("http://api.open-notify.org/astros.json");
    int httpCode = http.GET();

    if (httpCode == 200) {
      String input = http.getString();
      StaticJsonDocument<768> doc;
      deserializeJson(doc, input);
      int number = doc["number"];
      Serial.println(number);
    }
  }
  delay(3600000); //1 Stunde delay
}