Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Gartenautomation
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Deutsch
  • English
Menu

ESP32 Daten als CSV exportieren: Einfacher Zugriff über den Webbrowser

Posted on 24. März 202521. März 2025 by Stefan Draeger

In diesem Beitrag zeige ich dir, wie du die Verbrauchsdaten eines Shelly-Geräts auf einem ESP32-C3 Mikrocontroller speichern und anschließend bequem per REST-Schnittstelle als CSV-Datei exportieren kannst.
Im vorangegangenen Beitrag „Shelly 1PM + ESP32: Daten speichern & zeitgesteuert senden“ habe ich bereits erläutert, wie sich die Messwerte lokal sichern und automatisch an ThingSpeak übertragen lassen. Nun erweitern wir das Projekt um eine einfache und praktische Möglichkeit zur lokalen Datenweitergabe per Webbrowser.

ESP32 Daten als CSV exportieren: Einfacher Zugriff über den Webbrowser
Dieses Video auf YouTube ansehen.

Ein Leser hat daraufhin die sinnvolle Idee eingebracht, die gespeicherten Daten zusätzlich als CSV-Datei verfügbar zu machen – zum Beispiel für die Weiterverarbeitung in Excel oder zur lokalen Archivierung.

ESP32-C3 Super Mini mit Shelly PMs und Plug S
ESP32-C3 Super Mini mit Shelly PMs und Plug S

In diesem Beitrag zeige ich dir, wie du genau das umsetzen kannst: Der ESP32 stellt über einen kleinen integrierten Webserver die erfassten Messwerte als CSV-Datei zum Download bereit. So kannst du bequem über deinen Browser auf die Daten zugreifen – ganz ohne zusätzliche Tools oder Cloud-Zwang.

Inhaltsverzeichnis

  • Rückblick – Aufzeichnen der Daten auf dem Mikrocontroller
    • Datenarchiv für 5 Tage – Speicher automatisch verwalten
  • Auslesen der JSON-Daten vom Mikrocontroller
  • Schaltung am ESP32-C3
  • Programmieren einer REST-Schnittstelle in MicroPython
    • Schritt 1 – initialisieren des Servers
    • Schritt 2 – Anfragen akzeptieren und senden der Daten
      • parse_http_request(request) – HTTP-Anfrage analysieren
      • get_format_from_path(path) – Ausgabeformat bestimmen (JSON oder CSV)
      • respond_with_csv(client, data) – CSV-Antwort an den Client senden
      • respond_with_json(client, data) – JSON-Daten senden
      • handle_rest_request(server) – REST-Endpunkt zentral verarbeiten
  • Quellcode zum Abrufen der Daten vom ESP32 via REST-Schnittstelle
  • Fazit

Rückblick – Aufzeichnen der Daten auf dem Mikrocontroller

Die vom Shelly gelieferten Messdaten (Spannung, Strom, Leistungsaufnahme) werden über die integrierte REST-Schnittstelle regelmäßig vom ESP32-C3 Mikrocontroller abgefragt und lokal im Flash-Speicher gesichert. Die Speicherung erfolgt im JSON-Format, strukturiert nach Datum und Zeitstempel, sodass die Daten später einfach verarbeitet oder exportiert werden können – auch bei fehlender Internetverbindung.

👉 Tipp: Eine ausführliche Schritt-für-Schritt-Anleitung zum Aufbau, zur Programmierung und zur Datenspeicherung findest du in meinem Beitrag: „Shelly 1PM + ESP32: Daten speichern & zeitgesteuert senden“.

Datenarchiv für 5 Tage – Speicher automatisch verwalten

Um eine längere Verfügbarkeit der Daten zu gewährleisten, werden die erfassten Werte nun nicht mehr direkt nach dem Upload an ThingSpeak gelöscht. Stattdessen bleiben sie für maximal 5 Tage auf dem Mikrocontroller gespeichert. So kannst du die Daten zusätzlich als CSV-Datei im Browser abrufen oder lokal sichern – auch nachträglich.

Außerdem wurde das Messintervall von 5 auf 15 Minuten angepasst, um den Speicherverbrauch pro Tag zu reduzieren. Bei einem Intervall von 15 Minuten entstehen ca. 96 Datensätze pro Tag, was selbst bei mehreren Tagen gut in den internen 4 MB Flash-Speicher passt.

Die Datensätze werden nun täglich geprüft:
Ist ein Datumseintrag älter als 5 Tage, wird dieser automatisch gelöscht.
So bleibt der Speicherplatz effizient verwaltet, und du erhältst trotzdem eine kurze Historie deiner Energiedaten – ohne manuelles Eingreifen.

Auslesen der JSON-Daten vom Mikrocontroller

Wie bereits erwähnt, werden die erfassten Messdaten auf dem Mikrocontroller im JSON-Format gespeichert. Es gibt mehrere Möglichkeiten, diese Daten auszulesen.

Die einfachste Methode besteht darin, die Datei direkt über die Entwicklungsumgebung Thonny vom Mikrocontroller auf den PC zu kopieren. Dazu ist allerdings eine aktive Verbindung über ein USB-Datenkabel erforderlich – was in manchen Szenarien nicht möglich oder praktisch ist.

Eine clevere Alternative bietet eine einfache REST-Schnittstelle, die wir mit wenigen Zeilen Code selbst einrichten können. Das ist einer der vielen Vorteile von MicroPython: Es ermöglicht uns, schnell einen kleinen Webserver zu realisieren, über den wir die Daten bequem per Browser abrufen können – ganz ohne physische Verbindung.

Schaltung am ESP32-C3

Im Grunde benötigt man keine zusätzliche Schaltung denn es spielt sich alles ohne zusätzliche Komponenten ab. Jedoch habe ich drei LEDs angeschlossen um den aktuellen Zustand zu visualisieren.

Schaltung - ESP32-C3 mit LEDs
Schaltung – ESP32-C3 mit LEDs
  • Eine blaue LED für die aktive WiFi-Verbindung.
  • Eine rote LED für eventuelle Fehler.
  • Eine grüne LED als indikator für abruf der Daten vom Shelly.
ESP32-C3 - Fehler keine WiFi-Verbindung
ESP32-C3 – Fehler keine WiFi-Verbindung
ESP32-C3 erfolgreicher Abruf der Daten
ESP32-C3 erfolgreicher Abruf der Daten

Programmieren einer REST-Schnittstelle in MicroPython

In diesem Abschnitt programmieren wir die REST-Schnittstelle direkt auf dem ESP32 in MicroPython. Ziel ist es, zwei zentrale UseCases abzubilden:

  1. Download der Messdaten als CSV-Datei – zur einfachen Weiterverarbeitung z. B. in Microsoft Excel oder ähnlichen Anwendungen.
  2. Bereitstellung der Rohdaten im JSON-Format – ideal für Entwickler, APIs oder Tools, die die Daten maschinell weiterverarbeiten möchten.

Beide Varianten sind über den Webserver bequem über den Browser abrufbar – lokal, ohne Cloud-Anbindung, und ohne zusätzliche Software.

Ausgabe der gespeicherten Daten im JSON-Format
Ausgabe der gespeicherten Daten im JSON-Format
download der Daten als CSV-Datei vom ESP32-C3
download der Daten als CSV-Datei vom ESP32-C3

Der Download der CSV-Datei funktioniert besonders komfortabel: Der Chrome-Browser bietet die Datei beim Aufruf der entsprechenden URL direkt zum Speichern an – ganz ohne zusätzliches Zutun. Alles, was wir im Code tun müssen, ist, die CSV-Daten korrekt an den Client zu senden. Der Browser übernimmt den Rest automatisch.

Ich habe dir den Code bereits im Beitrag Shelly 1PM + ESP32: Daten speichern & zeitgesteuert senden ausführlich vorgestellt, hier soll es lediglich um die REST-Schnittstelle gehen. Du findest im nächsten Kapitel jedoch den kompletten Quellcode als ZIP-Datei zum download.

Schritt 1 – initialisieren des Servers

Da wir bereits eine aktive WiFi-Verbindung haben, können wir direkt mit der Initialisierung des Servers starten. Das Gute ist, das MicroPython dafür alles mitbringt und wir hier keine Zusätzlichen Module installieren müssen (wir müssen diese lediglich im Code importieren).

# Module für Netzwerk, Datenverarbeitung und Zugriff auf gespeicherte Daten
import socket
import ujson
import datastore
import util
import logger

from configuration import REST_SERVER_PORT

# Initialisiert den REST-Server auf dem angegebenen Port (Standard: 80)
def init_rest_server(port=REST_SERVER_PORT):
    addr = socket.getaddrinfo('0.0.0.0', port)[0][-1]  # Ermittelt die Adresse
    s = socket.socket()              # Erstellt einen TCP-Socket
    s.bind(addr)                     # Bindet den Socket an die Adresse
    s.listen(1)                      # Wartet auf Verbindungen (max. 1 gleichzeitig)
    s.setblocking(False)            # Setzt den Socket auf nicht-blockierend (wichtig für Main-Loop)
    logger.debugLog(f'REST-Server läuft auf Port {port}')
    return s

Schritt 2 – Anfragen akzeptieren und senden der Daten

Die nächste Funktion beinhaltet das akzeptieren einer Anfrage vom Client und das senden der Daten.

parse_http_request(request) – HTTP-Anfrage analysieren

Diese Funktion extrahiert aus der ersten Zeile der eingehenden HTTP-Anfrage die HTTP-Methode (z. B. GET) sowie den angeforderten Pfad (z. B. /data?format=csv). So wissen wir, auf welche Ressource zugegriffen werden soll.

def parse_http_request(request):
    try:
        request_line = request.split('\r\n')[0]
        method, path, _ = request_line.split()
        return method, path
    except:
        return None, None

get_format_from_path(path) – Ausgabeformat bestimmen (JSON oder CSV)

Hier wird geprüft, ob in der URL ein format=-Parameter übergeben wurde. Falls ja, wird das gewünschte Format zurückgegeben – standardmäßig ist json voreingestellt. Beispiel:
/data?format=csv → Ausgabe als CSV-Datei.

def get_format_from_path(path):
    format_type = "json"
    if '?' in path:
        query = path.split('?')[1]
        params = query.split('&')
        for p in params:
            if '=' in p:
                key, value = p.split('=')
                if key == 'format':
                    format_type = value.lower()
    return format_type

respond_with_csv(client, data) – CSV-Antwort an den Client senden

Diese Funktion übernimmt den CSV-Export: Die Daten werden in CSV umgewandelt und mit den passenden HTTP-Headern an den Client zurückgeschickt. Browser wie Chrome starten bei Content-Type: text/csv automatisch den Dateidownload.

def respond_with_csv(client, data):
    csv_data = util.dict_to_csv(data)
    client.send("HTTP/1.1 200 OK\r\n")
    client.send("Content-Type: text/csv\r\n")
    client.send("Access-Control-Allow-Origin: *\r\n")
    client.send("Connection: close\r\n\r\n")
    client.send(csv_data)

respond_with_json(client, data) – JSON-Daten senden

Hier werden die Daten als JSON an den Client gesendet. Das ist besonders hilfreich für Entwickler, APIs oder Automatisierungsskripte, die die Rohdaten weiterverarbeiten möchten.

def respond_with_json(client, data):
    json_data = ujson.dumps(data)
    client.send("HTTP/1.1 200 OK\r\n")
    client.send("Content-Type: application/json\r\n")
    client.send("Access-Control-Allow-Origin: *\r\n")
    client.send("Connection: close\r\n\r\n")
    client.send(json_data)

handle_rest_request(server) – REST-Endpunkt zentral verarbeiten

Dies ist die Hauptfunktion, die die REST-Schnittstelle steuert. Sie akzeptiert eingehende Verbindungen, wertet die Anfrage aus, lädt die Daten und entscheidet anhand des Formats, ob JSON oder CSV gesendet werden soll. Für ungültige Pfade wird eine einfache 404-Meldung zurückgegeben.

def handle_rest_request(server):
    try:
        client, addr = server.accept()
    except OSError:
        return

    try:
        request = client.recv(1024).decode('utf-8')
        method, path = parse_http_request(request)

        if method == 'GET' and path.startswith('/data'):
            format_type = get_format_from_path(path)
            data = datastore.read_json_file()

            if format_type == 'csv':
                respond_with_csv(client, data)
            else:
                respond_with_json(client, data)
        else:
            client.send("HTTP/1.1 404 Not Found\r\n")
            client.send("Content-Type: text/plain\r\n\r\n")
            client.send("Seite nicht gefunden.")
    except Exception as e:
        logger.debugLog(f"Fehler beim Verarbeiten: {e}")
    finally:
        client.close()

Quellcode zum Abrufen der Daten vom ESP32 via REST-Schnittstelle

Den Quellcode habe ich in mehrere Dateien aufgeteilt und so deutlich übersichtlicher gestaltet.

  • main.py => Hauptprogramm
  • wifi.py => Aufbau der WiFi-Verbindung
  • datastore.py => Funktionen zum Daten vom Mikrocontroller zu lesen und zu speichern
  • led.py => LEDs steuern (WiFi, Fehler, Datenabruf)
  • logger.py => Datenlogger für Fehler-/Infomeldungen
  • util.py => Hilfsfunktionen für das Programm (Datumformatieren, etc.)
  • configuration.py => Werte für die WiFi-Verbindung, Server-Port, etc.
fertiges Programm zum speichern von Daten eines Shellys auf dem ESP32-C3 und abrufen via REST-SchnittstelleHerunterladen
Quellcode – main.py
# Standardbibliothek für Zeitfunktionen
import time

# Eigene Module
import wifi                # WLAN-Verbindung herstellen
import led                 # LEDs zur Statusanzeige
import fetchShellyData as shelly  # Modul zum Abrufen von Shelly-Daten via HTTP
import util                # Hilfsfunktionen, z. B. zum Parsen der Daten oder RTC-Sync
import logger              # Debug-Logging
import datastore           # Daten lokal speichern/verwalten
import machine             # MicroPython-Hardwarefunktionen (z. B. Reset, Pin, etc.)
import server as restServer  # REST-API-Modul zum Bereitstellen von Daten

# Zeitintervall zwischen zwei Datenabrufen (in Millisekunden)
from configuration import FETCH_INTERVAL_MS

# Zeitpunkt des letzten Abrufs merken
letzter_aufruf = time.ticks_ms()

# Aufgabe: Daten vom Shelly holen, aufbereiten und speichern
def fetchData_task():
    data = shelly.fetch_shelly_data()               # Rohdaten vom Shelly abfragen (HTTP GET)
    shellyData = util.extract_shelly_values(data)   # Wichtige Werte extrahieren (current, voltage, apower)
    led.receivedDataLED()                           # LED blinkt kurz zur Bestätigung des Dateneingangs
    datastore.read_json_file()                      # Vorherige Daten aus Datei laden
    datastore.remove_old_entries()                  # Alte Einträge ggf. löschen (z. B. > 5 Tage alt)
    datastore.add_entry(shellyData)                 # Aktuelle Daten hinzufügen
    datastore.save_data_to_file()                   # Daten wieder in Datei speichern

# Hauptprogramm
try:
    led.setErrorLED(False)                          # Fehler-LED ausschalten
    led.setWiFiActive(False)                        # WiFi-LED ebenfalls deaktivieren (wird gleich gesetzt)

    isWiFiConnected = wifi.connect_wifi()           # Mit WLAN verbinden
    logger.debugLog('WiFi Verbindung: '+ ('AN' if isWiFiConnected else 'AUS'))

    if isWiFiConnected:
        if util.sync_rtc():                         # Systemzeit mit NTP synchronisieren
            server = restServer.init_rest_server()  # REST-API initialisieren
            while True:
                restServer.handle_rest_request(server)  # HTTP-Anfragen bearbeiten

                jetzt = time.ticks_ms()             # Aktueller Zeitstempel
                if time.ticks_diff(jetzt, letzter_aufruf) >= FETCH_INTERVAL_MS:
                    fetchData_task()                # Nur alle 5 Sekunden Daten abrufen
                    letzter_aufruf = jetzt
        else:
            led.setErrorLED(True)                   # RTC-Sync fehlgeschlagen → Fehler anzeigen
    else:
        led.setErrorLED(True)                       # WLAN-Verbindung fehlgeschlagen → Fehler anzeigen

    led.setWiFiActive(False)                        # WLAN-LED am Ende wieder deaktivieren

except Exception as e:
    led.setErrorLED(True)                           # Fehler-LED einschalten bei unerwartetem Fehler
    print(e)                                        # Fehlerausgabe zur Analyse

Quellcode – wifi.py
# Importiere Netzwerksteuerung für WLAN
import network
import time
import led
from configuration import WIFI_SSID as SSID, WIFI_PASSWORD as PASSWORD

# WLAN-Zugangsdaten (→ solltest du später z. B. in eine separate config.py auslagern)
SSID = "FRITZBox7590GI24"
PASSWORD = "22894580214767401850"

# Verbindet das Gerät mit dem WLAN-Netzwerk
def connect_wifi():
    global SSID, PASSWORD

    # WLAN-Schnittstelle im Station-Modus (STA_IF = Client-Modus)
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)  # Aktiviert WLAN

    # Wenn noch keine Verbindung besteht, versuche zu verbinden
    if not wlan.isconnected():
        print("Verbinde mit WLAN...")
        wlan.connect(SSID, PASSWORD)

        # Warte auf Verbindung (max. 10 Sekunden)
        timeout = 10  # Sekunden
        while not wlan.isconnected() and timeout > 0:
            led.blink(0.25)        # Status-LED blinkt während Verbindungsversuch
            timeout -= 0.5
            print(".", end="")     # Ausgabe eines Punkts pro Versuch (optional)

    # Ergebnis prüfen
    if wlan.isconnected():
        print("\nWLAN verbunden.")
        print("IP-Adresse:", wlan.ifconfig()[0])  # Ausgabe der zugewiesenen IP-Adresse
        led.setWiFiActive(True)                   # WLAN-LED einschalten
        return True
    else:
        print("\nVerbindung fehlgeschlagen.")
        led.setWiFiActive(False)                  # WLAN-LED ausschalten
        return False

Quellcode – datastore.py
# JSON-Verarbeitung und Logging
import ujson
import logger
import util

from configuration import DATASTORE_FILENAME as filename

# Globale Datenstruktur zum Zwischenspeichern der Daten im RAM
data = {}

# Liest die JSON-Datei ein und lädt sie als Dictionary in die globale Variable `data`
def read_json_file():
    global data, filename
    try:
        with open(filename, 'r') as file:
            data = ujson.load(file)  # Inhalt der Datei in `data` laden
        return data
    except OSError:
        logger.debugLog(f"Datei '{filename}' wurde nicht gefunden.", "ERROR")
    except ValueError:
        logger.debugLog(f"Fehler beim Einlesen der Datei '{filename}': Ungültiges JSON-Format.","ERROR")

# Fügt einen neuen Messwert in die Datenstruktur ein
def add_entry(values_dict):
    global data

    # Extrahiere Datum im Format DD.MM.YYYY und Zeitstempel (Unixzeit)
    timestamp_str = values_dict['unixtime']
    date_str = util.timestamp_to_date(values_dict['unixtime'])

    # Wenn der Tag noch nicht im Dictionary ist, anlegen
    if date_str not in data:
        data[date_str] = {}

    # Entferne den Zeitstempel aus dem Dictionary der Messwerte (ist schon im Key enthalten)
    values_dict.pop('unixtime')

    # Werte unter dem entsprechenden Datum und Zeitstempel speichern
    data[date_str][timestamp_str] = values_dict

# Speichert die globale `data`-Struktur als JSON-Datei
def save_data_to_file():
    global data, filename
    try:
        with open(filename, "w") as file:
            ujson.dump(data, file)  # Schreibe Daten in Datei
            logger.debugLog("Daten erfolgreich gespeichert.")
    except OSError as osError:
        logger.debugLog("Fehler beim Schreiben der Datei. {osError}", "ERROR")

# Löscht alle Datums-Einträge, die älter als X Tage sind (Standard: 5 Tage)
def remove_old_entries():
    global data

    # Prüfe, welche Datums-Schlüssel älter als erlaubt sind
    keys_to_delete = [key for key in data if util.is_older_than_days(key)]

    # Entferne alte Einträge
    for key in keys_to_delete:
        del data[key]

Quellcode – led.py
# Importiere Pin-Steuerung und Zeitfunktionen
from machine import Pin
import time

# Initialisierung der LED-Pins (Anpassen je nach Board / Verkabelung)
ledWiFi = Pin(2, Pin.OUT)    # LED für WLAN-Status
ledError = Pin(3, Pin.OUT)   # LED für Fehleranzeige
ledData = Pin(4, Pin.OUT)    # LED zeigt an, dass neue Daten empfangen wurden

# Schaltet die WLAN-LED ein oder aus
def setWiFiActive(value):
    ledWiFi.value(1 if value else 0)

# Blinkt die WLAN-LED einmal für das angegebene Zeitintervall (z. B. beim Verbindungsaufbau)
def blink(intervall):
    setWiFiActive(True)
    time.sleep(intervall)
    setWiFiActive(False)
    time.sleep(intervall)

# Schaltet die Fehler-LED ein oder aus
def setErrorLED(value):
    ledError.value(1 if value else 0)

# Blinkt kurz die Daten-LED, wenn neue Werte gespeichert wurden
def receivedDataLED():
    ledData.value(1)
    time.sleep(0.25)
    ledData.value(0)
    time.sleep(0.25)

Quellcode – logger.py
import time

def debugLog(text, level="INFO"):
    try:
        print(text)
        now = time.localtime()
        datum = "{:02d}.{:02d}.{:04d}".format(now[2], now[1], now[0])
        uhrzeit = "{:02d}:{:02d}:{:02d}".format(now[3], now[4], now[5])
        log_line = f"[{datum} {uhrzeit}] [{level.upper()}] {text}\n"

        with open("debug.log", "a") as log_file:
            log_file.write(log_line)
    except Exception as e:
        print("Fehler beim Schreiben ins Log:", e)
Quellcode – util.py
# Standard- und Projektmodule
import json
import logger
import ntptime
import time
import machine

from configuration import DATA_RETENTION_DAYS

# Extrahiert nur die benötigten Messwerte aus der vollständigen Shelly-Antwort
def extract_shelly_values(data):
    try:
        voltage = data["switch:0"]["voltage"]
        apower = data["switch:0"]["apower"]
        current = data["switch:0"]["current"]
        unixtime = data["sys"]["unixtime"]

        # Gibt ein flaches Dictionary mit den wichtigsten Werten zurück
        return {
            "voltage": voltage,
            "apower": apower,
            "current": current,
            "unixtime": unixtime
        }
    except KeyError as e:
        logger.debugLog("Fehlender Wert im JSON: {e}")
        return None

# Wandelt die aktuelle RTC-Zeit in das Format DD.MM.YYYY um (z. B. für die Datenstruktur im Speicher)
def timestamp_to_date(timestamp):
    try:
        t = machine.RTC().datetime()
        return "{:02d}.{:02d}.{:04d}".format(t[2], t[1], t[0])
    except Exception as e:
        logger.debugLog(e)
        return "-error-"

# Gleiche Funktion wie oben, aber klar benannt (könnte ggf. ersetzt oder vereinheitlicht werden)
def formatDate():
    t = machine.RTC().datetime()
    return "{tag:02d}.{monat:02d}.{jahr:4d}".format(tag = t[2],monat= t[1],jahr= t[0])

# Synchronisiert die Echtzeituhr (RTC) mit einem NTP-Server über das Internet
def sync_rtc():
    try:
        ntptime.settime()
        logger.debugLog("RTC erfolgreich synchronisiert.")
        return True
    except Exception as e:
        print(e)
        logger.debugLog("Fehler bei der RTC-Synchronisation. {e}", "ERROR")
        return False

# Prüft, ob ein gegebenes Datum älter ist als eine bestimmte Anzahl an Tagen
def is_older_than_days(date_str, days=DATA_RETENTION_DAYS):
    try:
        # Aktuelles Datum vom RTC-Modul holen
        today = machine.RTC().datetime()
        current_timestamp = time.mktime((today[0], today[1], today[2], 0, 0, 0, 0, 0))

        # Umwandlung des gegebenen Datumsstrings in einen Zeitstempel
        tag, monat, jahr = map(int, date_str.split("."))
        entry_timestamp = time.mktime((jahr, monat, tag, 0, 0, 0, 0, 0))

        # Vergleich
        delta = current_timestamp - entry_timestamp
        return delta > days * 86400  # 86400 Sekunden = 1 Tag
    except Exception as e:
        logger.debugLog("Fehler bei Datumsprüfung: {e}", "ERROR")
        return False

# Prüft, ob Internet verfügbar ist (z. B. für NTP oder externe APIs)
def internet_available():
    try:
        response = urequests.get("http://www.google.com")
        if response.status_code == 200:
            response.close()
            logger.debugLog("Internetverbindung verfügbar.")
            return True
        else:
            logger.debugLog("Internetverbindung nicht erfolgreich. Status: "+ response.status_code, "ERROR")
            response.close()
            return False
    except Exception as e:
        logger.debugLog("Kein Internetzugriff: {e}", "ERROR")
        return False

# Konvertiert die verschachtelte Datenstruktur in ein CSV-Format mit Semikolon als Trennzeichen
def dict_to_csv(data):
    # Header-Zeile definieren
    csv_lines = ["date;timestamp;current;voltage;apower"]
    for date, timestamps in data.items():
        for ts, values in timestamps.items():
            # Komma statt Punkt für Dezimaltrennung (deutsches Format)
            current = str(values.get('current', '')).replace('.', ',')
            voltage = str(values.get('voltage', '')).replace('.', ',')
            apower = str(values.get('apower', '')).replace('.', ',')
            # Zeile zusammenbauen
            line = f"{date};{ts};{current};{voltage};{apower}"
            csv_lines.append(line)
    return '\n'.join(csv_lines)

Quellcode – configuration.py
WIFI_SSID = "abc"
WIFI_PASSWORD = "123"

# Shelly API-Endpunkt
SHELLY_URL = "http://192.168.178.38/rpc/Shelly.GetStatus"

# Dateiname für gespeicherte Daten
DATASTORE_FILENAME = "data.json"

# REST-Server
REST_SERVER_PORT = 80

# Datenabrufintervall in Millisekunden
FETCH_INTERVAL_MS = 5000  # z. B. alle 5 Sekunden

# Maximale Aufbewahrungszeit (z. B. 5 Tage)
DATA_RETENTION_DAYS = 5

Fazit

Die Umsetzung einer REST-Schnittstelle mit MicroPython ist erstaunlich unkompliziert und bietet jede Menge Potenzial. Wie in diesem Beitrag gezeigt, lassen sich so die lokal gespeicherten Verbrauchsdaten vom ESP32 ganz einfach im CSV- oder JSON-Format abrufen – direkt im Browser und ohne zusätzliche Tools.

Doch damit ist noch lange nicht Schluss: Die REST-Schnittstelle lässt sich flexibel erweitern – etwa um zusätzliche Parameter zur Filterung der Daten, z. B. nach Datum oder Uhrzeit.
Wenn dich das interessiert, zeige ich dir gerne in einem weiteren Beitrag, wie du deine Ausgaben gezielt eingrenzen und nur die Daten abrufen kannst, die du wirklich brauchst.

Hinterlasse mir einen Kommentar, wenn du dir diesen erweiterten Beitrag wünschst!

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen
Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

link zu Fabook
link zu LinkedIn
link zu YouTube
link zu TikTok
link zu Pinterest
link zu Instagram
  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}