ESP32 REST-API-Server mit JSON - Komplettes Tutorial

WebServerJson-Beispiel - REST-API-Server

Übersicht

Dieses Beispiel zeigt, wie man einen REST-API-Server auf dem ESP32 erstellt, der JSON-Anfragen und -Antworten verarbeitet, ideal für moderne Webanwendungen und Backends mobiler Apps.

Funktionen

  • REST-API-Endpunkte mit der Verarbeitung von JSON-Anfragen und JSON-Antworten
  • POST-Anfrageverarbeitung mit dem Parsen von JSON-Daten
  • GET-Endpunkte zur Datenabfrage
  • Professionelle JSON-Antworten mit passenden HTTP-Statuscodes
  • Fehlerbehandlung mit passenden JSON-Fehlernachrichten
  • CORS-Unterstützung für Cross-Origin-Anfragen

Erforderliche Hardware

1×ESP32 ESP-WROOM-32 Entwicklungsmodul
1×USB-Kabel Typ-A zu Typ-C (für USB-A PC)
1×USB-Kabel Typ-C zu Typ-C (für USB-C PC)
1×(Empfohlen) Schraubklemmen-Erweiterungsboard für ESP32
1×(Empfohlen) Breakout Expansion Board for ESP32
1×(Empfohlen) Stromverteiler für ESP32

Oder Sie können die folgenden Kits kaufen:

1×DIYables ESP32 Starter-Kit (ESP32 enthalten)
1×DIYables Sensor-Kit (30 Sensoren/Displays)
1×DIYables Sensor-Kit (18 Sensoren/Displays)
Offenlegung: Einige der in diesem Abschnitt bereitgestellten Links sind Amazon-Affiliate-Links. Wir können eine Provision für Käufe erhalten, die über diese Links getätigt werden, ohne zusätzliche Kosten für Sie. Wir schätzen Ihre Unterstützung.

Bibliotheksinstallation

Folgen Sie diesen Anweisungen Schritt für Schritt:

  • Wenn dies das erste Mal ist, dass Sie den ESP32 verwenden, sehen Sie sich das Tutorial zur Einrichtung der ESP32-Umgebung in der Arduino IDE an: Einrichtung der ESP32-Umgebung in der Arduino IDE
  • Verbinden Sie das ESP32-Board über ein USB-Kabel mit Ihrem Computer.
  • Starten Sie die Arduino IDE auf Ihrem Computer.
  • Wählen Sie das passende ESP32-Board (z. B. ESP32) und den COM-Port aus.
  • Öffnen Sie den Bibliotheksverwalter, indem Sie auf das Symbol Bibliotheksverwalter auf der linken Seite der Arduino IDE klicken.
  • Suchen Sie nach Web Server for ESP32 und finden Sie die mWebSockets von DIYables.
  • Klicken Sie auf die Schaltfläche Installieren, um die mWebSockets-Bibliothek hinzuzufügen.
ESP32-Webserver-Bibliothek

Webserver JSON-Beispiel

  • In der Arduino IDE, gehen Sie zu Datei Beispiele Webserver für ESP32 WebServerJson Beispiel, um den Beispielcode zu öffnen

API-Endpunkte

GET /api/daten

Gibt eine Erfolgsmeldung mit Zeitstempel im JSON-Format zurück.

Antwort:

{ "status": "success", "message": "GET request received", "timestamp": 12345 }

Der Zeitstempelwert gibt Millisekunden seit dem Start des ESP32 an (aus der Funktion millis()).

POST /api/daten

Nimmt JSON-Daten entgegen und gibt den empfangenen Schlüsselwert zurück.

Anfrage:

{ "key": "your_value" }

Antwort:

{ "status": "success", "message": "Data received", "received_key": "your_value" }

Installationsanweisungen

1. Netzwerkkonfiguration

Bearbeiten Sie die WLAN-Zugangsdaten in der WebServerJson.ino-Datei:

const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

2. Code hochladen und Ausgabe überwachen

  1. Verbinden Sie Ihren ESP32 mit Ihrem Computer
  2. Wählen Sie das richtige Board und den richtigen Port in der Arduino IDE aus
  3. Laden Sie die WebServerJson.ino-Skizze hoch
  4. Öffnen Sie den Serial Monitor (9600 Baud)
  5. Warten Sie auf die WiFi-Verbindung
  6. Notieren Sie die angezeigte IP-Adresse
  7. Wenn Sie die IP-Adresse im Serial Monitor nicht sehen, drücken Sie die Reset-Taste am ESP32-Board

Verwendung

Testen mit cURL

Ersetze your-esp32-ip durch die tatsächliche IP-Adresse, die in Ihrem seriellen Monitor angezeigt wird.

Test-GET-Anfrage
curl -X GET http://your-esp32-ip/api/data

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X GET http://your-esp32-ip/api/data { "status": "success", "message": "GET request received", "timestamp": 12345 }

Der Zeitstempel zeigt Millisekunden seit dem Start des ESP32 an.

Test-POST-Anfrage mit JSON-Daten
curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"test_value\"}"

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"test_value\"}" { "status": "success", "message": "Data received", "received_key": "test_value" }
Test-POST-Anfrage mit unterschiedlichen Daten
curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"hello_world\"}"

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"hello_world\"}" { "status": "success", "message": "Data received", "received_key": "hello_world" }
Test: Ungültiges JSON (Fehlerantwort)
curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{invalid json}"

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{invalid json}" { "status": "error", "message": "Invalid JSON" }
Test fehlender JSON-Body (Fehlerantwort)
curl -X POST http://your-esp32-ip/api/data

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X POST http://your-esp32-ip/api/data { "status": "error", "message": "No JSON data received" }
Test Nicht unterstützte Methode (Fehlerantwort)
curl -X PUT http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"test\"}"

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X PUT http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"key\": \"test\"}" { "status": "error", "message": "Method not allowed" }
Test eines nicht vorhandenen Endpunkts (404-Fehler)
curl -X GET http://your-esp32-ip/api/nonexistent

Erwartete Ausgabe:

Command Prompt
C:\Users\youruser>curl -X GET http://your-esp32-ip/api/nonexistent <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>404 Not Found</title> </head> <body> <h1>404 - Page Not Found</h1> <p>Method: GET</p> <p>Sorry, we couldn't find that page!</p> <a href="/">Return to Home</a> </body> </html>

Testen mit Postman

Test GET-Anfrage
  1. Erstelle eine neue GET-Anfrage
  2. Setze die URL auf http://your-esp32-ip/api/data
  3. Sende die Anfrage
  4. Überprüfe, ob die Antwort Status, Nachricht und Zeitstempel enthält
Test-POST-Anfrage
  1. Erstelle eine neue POST-Anfrage
  2. Setze die URL auf http://your-esp32-ip/api/data fest
  3. Füge Header hinzu: Content-Type: application/json
  4. Füge den JSON-Body hinzu: {"key": "test_value"}
  5. Sende die Anfrage
  6. Überprüfe, ob die Antwort den empfangenen Schlüsselwert anzeigt

Fehlerantworten testen

Testen Sie die Fehlerbehandlung, indem Sie ungültige Anfragen senden, wie im Beispielcode gezeigt:

Fehlende JSON-Daten
curl -X POST http://your-esp32-ip/api/data

{"status": "error","message": "Keine JSON-Daten empfangen"}

Ungültiges JSON-Format
curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{invalid json}"

Erwartet: {"status": "Fehler","message": "Ungültiges JSON"}

Fehlendes Schlüsselfeld
curl -X POST http://your-esp32-ip/api/data -H "Content-Type: application/json" -d "{\"other_field\": \"value\"}"

Erwartet: Der Schlüssel wird standardmäßig auf "none" gesetzt, wie im Beispielcode: doc["key"] | "none"

Nicht unterstützte HTTP-Methode
curl -X DELETE http://your-esp32-ip/api/data

{"status": "error","message": "Methode nicht erlaubt"}

Code-Erklärung

Routen-Konfiguration

// Configure API routes server.addRoute("/api/data", handleApiData);

Funktionssignatur des Handlers

Alle Handler-Funktionen müssen diese Signatur befolgen:

void handleApiData(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { // Handler implementation }

Methodenerkennung und JSON-Verarbeitung

void handleApiData(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { Serial.print("[API] "); Serial.print(method); Serial.print(" request received"); if (method == "POST") { if (jsonData.length() == 0) { Serial.println("Error: No JSON data received"); client.println("HTTP/1.1 400 Bad Request"); client.println("Content-Type: application/json"); client.println("Connection: close"); client.println(); client.print("{\"status\": \"error\",\"message\": \"No JSON data received\"}"); return; } StaticJsonDocument<200> doc; DeserializationError error = deserializeJson(doc, jsonData); if (!error) { const char* key = doc["key"] | "none"; String response = JSON_RESPONSE; response.replace("%KEY%", key); server.sendResponse(client, response.c_str(), "application/json"); } else { client.println("HTTP/1.1 400 Bad Request"); client.println("Content-Type: application/json"); client.println("Connection: close"); client.println(); client.print("{\"status\": \"error\",\"message\": \"Invalid JSON\"}"); } } else if (method == "GET") { String response = JSON_GET_RESPONSE; response.replace("%TIMESTAMP%", String(millis())); server.sendResponse(client, response.c_str(), "application/json"); } else { client.println("HTTP/1.1 405 Method Not Allowed"); client.println("Content-Type: application/json"); client.println("Connection: close"); client.println(); client.print("{\"status\":\"error\",\"message\":\"Method not allowed\"}"); } }

Integrationsbeispiele

JavaScript-Frontend

// Control LED async function controlLED(action) { try { const response = await fetch('http://your-esp32-ip/api/led', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ action: action }) }); const result = await response.json(); console.log('LED control result:', result); } catch (error) { console.error('Error:', error); } } // Get sensor data async function getSensorData() { try { const response = await fetch('http://your-esp32-ip/api/sensor'); const data = await response.json(); console.log('Sensor data:', data); } catch (error) { console.error('Error:', error); } }

Python-Client

import requests import json

LED steuern

def control_led(action): url = "http://your-esp32-ip/api/led" data = {"action": action} response = requests.post(url, json=data) return response.json()

Status abrufen

def get_status(): url = "http://your-esp32-ip/api/status" response = requests.get(url) return response.json()

Verwendung

result = control_led("on") print(result) status = get_status() print(status)

Fehlerbehandlung

HTTP-Statuscodes

  • 200: Erfolg
  • 400: Ungültige Anfrage (ungültiges JSON, fehlende Parameter)
  • 404: Endpunkt nicht gefunden
  • 405: Methode nicht erlaubt
  • 500: Interner Serverfehler

Format der Fehlermeldung

Basierend auf dem tatsächlichen Beispielcode geben verschiedene Fehler spezifische Meldungen zurück:

Fehler: Fehlende JSON-Daten
{ "status": "error", "message": "No JSON data received" }

Zurückgegeben, wenn: POST-Anfrage wird ohne JSON-Body gesendet

Ungültiger JSON-Formatfehler
{ "status": "error", "message": "Invalid JSON" }

Zurückgegeben, wenn: JSON-Daten können nicht analysiert werden (Syntaxfehler)

Fehler: Methode nicht erlaubt
{ "status": "error", "message": "Method not allowed" }

Wird zurückgegeben, wenn: Nicht unterstützte HTTP-Methoden (PUT, DELETE, PATCH usw.) verwendet werden.

Fehler 404 – Seite nicht gefunden
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>404 Not Found</title> </head> <body> <h1>404 - Page Not Found</h1> <p>Method: [HTTP_METHOD]</p> <p>Sorry, we couldn't find that page!</p> <a href="/">Return to Home</a> </body> </html>

Zurückgegeben, wenn: Zugriff auf nicht vorhandene Endpunkte

Anpassung

Neue Handler-Funktionen hinzufügen

// Create additional handler for a new endpoint void handleApiStatus(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { if (method == "GET") { String json = "{\"status\":\"online\",\"uptime\":" + String(millis() / 1000) + "}"; server.sendResponse(client, json.c_str(), "application/json"); } else { client.println("HTTP/1.1 405 Method Not Allowed"); client.println("Content-Type: application/json"); client.println("Connection: close"); client.println(); client.print("{\"status\":\"error\",\"message\":\"Method not allowed\"}"); } } // Register the new route in setup() server.addRoute("/api/status", handleApiStatus);

Vorlagenbasierte JSON-Antworten

Das Beispiel verwendet Template-Strings für eine konsistente JSON-Formatierung:

const char JSON_RESPONSE[] PROGMEM = R"rawliteral( { "status": "success", "message": "Data received", "received_key": "%KEY%" } )rawliteral"; // Usage in handler String response = JSON_RESPONSE; response.replace("%KEY%", extractedValue); server.sendResponse(client, response.c_str(), "application/json");

Fehlerbehebung

Häufige Probleme

Verbindungsprobleme

Wenn Sie sich nicht mit den API-Endpunkten verbinden können:

  1. Vergewissern Sie sich, dass Ihr ESP32 mit WiFi verbunden ist (prüfen Sie den seriellen Monitor).
  2. Stellen Sie sicher, dass Ihr Client und der ESP32 im selben Netzwerk sind.
  3. Überprüfen Sie, ob die IP-Adresse korrekt ist.
  4. Vergewissern Sie sich, dass der ESP32 nicht zurückgesetzt wurde (was die IP-Adresse ändern würde).

JSON-Parsing-Fehler

Wenn Sie auf „Invalid JSON“-Antworten stoßen:

  1. Stellen Sie sicher, dass der Content-Type-Header auf application/json gesetzt ist
  2. Überprüfen Sie, ob Ihre JSON-Syntax gültig ist
  3. Überprüfen Sie, dass Sonderzeichen ordnungsgemäß maskiert sind
  4. Stellen Sie sicher, dass die JSON-Nutzlast nicht zu groß ist (aktuelles Limit: 200 Bytes)

POST-Anfrageprobleme

Wenn POST-Anfragen „Keine JSON-Daten empfangen“ zurückgeben:

  1. Stellen Sie sicher, dass die Anfrage einen JSON-Body enthält
  2. Prüfen Sie, ob der Content-Length-Header korrekt gesetzt ist
  3. Stellen Sie sicher, dass die HTTP-Methode tatsächlich POST ist
  4. Testen Sie es mit einem einfachen JSON wie {"key": "test"}

Gedächtnisprobleme

Wenn der ESP32 nicht mehr reagiert:

  1. Überwache den Speicherverbrauch - das StaticJsonDocument verwendet 200 Byte
  2. Reduziere bei Bedarf die Größe der JSON_RESPONSE-Vorlage
  3. Erwäge die Verwendung von DynamicJsonDocument für Daten variabler Größe
  4. Überprüfe Speicherlecks in benutzerdefinierten Handler-Funktionen

Tipps zur Leistung

JSON-Verarbeitung optimieren

// Use appropriate document size for your data StaticJsonDocument<200> doc; // For small JSON objects StaticJsonDocument<1024> doc; // For larger JSON objects // Reuse string objects to reduce memory allocation String response; response.reserve(256); // Pre-allocate space response = JSON_RESPONSE; response.replace("%KEY%", value);

Effiziente Antwortverarbeitung

// Send responses directly for simple cases client.print(F("{\"status\":\"ok\",\"value\":")); client.print(sensorValue); client.print(F("}")); // Use PROGMEM for large static responses const char LARGE_RESPONSE[] PROGMEM = R"({ "status": "success", "data": { ... } })";

Nächste Schritte

  • Erkunde WebServerQueryStrings.ino zur Verarbeitung von URL-Parametern
  • Probiere WebServerWithWebSocket.ino für die Echtzeit-Kommunikation
  • Erwäge die Integration mit Datenbanken oder Cloud-Diensten

Lernressourcen

※ UNSERE NACHRICHTEN

  • Sie können gerne den Link zu diesem Tutorial teilen. Bitte verwenden Sie jedoch unsere Inhalte nicht auf anderen Websites. Wir haben viel Mühe und Zeit in die Erstellung der Inhalte investiert, bitte respektieren Sie unsere Arbeit!