Node-RED · Preis und CO2

Strompreis und CO2 in Node-RED nutzen, ohne lange zu klicken

Wenn du Node-RED nutzt, ist der einfachste Einstieg ein importierbarer Flow. Du fügst ihn ein, klickst auf Deploy und siehst sofort Preis, CO2, Zeitfenster und die wichtigsten Meta-Felder im Debug.

Warum dieser Weg sinnvoll ist

Node-RED kann JSON-APIs direkt verarbeiten. Du brauchst deshalb keine Spezialintegration, sondern nur einen kleinen Flow mit Inject, Function, HTTP Request und Debug.

Für Einsteiger wichtig

Im Beispiel ist der HTTP-Request so konfiguriert, dass er die Antwort direkt als geparstes Objekt zurückgibt. Dann musst du später keine JSON-Strings manuell auseinandernehmen.

Empfohlener Endpunkt

Für Node-RED gibt es einen eigenen Summary-Pfad mit den wichtigsten Feldern für erste Automationen und mit Meta-Feldern für Limits und API-Key-Status.

https://api.energypriceforecast.eu/api/v1/node-red/summary?country=de&hours=48&window_hours=4
Sofort sichtbarDer Beispiel-Flow schreibt die wichtigsten Werte direkt in msg.*.
Einfach weiterverwendbarSpäter kannst du dieselben Felder für Switch-, Delay- oder Dashboard-Logik nutzen.
Meta inklusivemsg.api_key_state, msg.allowed_horizon_hours und mehr kommen direkt mit.

Was die API genau liefert

Der Endpunkt liefert eine kompakte Automation-Summary. Für Node-RED ist das praktisch, weil du die Antwort einerseits direkt für einfache Flows nutzen kannst, andererseits aber genug Struktur für spätere Erweiterungen bekommst.

Teil Inhalt Nutzen
flatDie einfachsten Felder wie aktueller Preis, aktuelles CO2, aktive beste Fenster und Restlaufzeiten.Sofort für msg.* nutzbar.
priceAktueller Preis-Slot sowie best_window und next_full_window als Objekte.Mehr Kontext für eigene Flows.
co2Aktueller CO2-Slot sowie best_window und next_full_window.Für CO2-orientierte Entscheidungen.
sourceMetadaten zu Day-Ahead und Forecast.Wichtig für Einordnung und Debug.
metaZugriffs- und Vertragsinfos wie API-Key-Status, erlaubter Horizont und Tageszähler.Sauberes Monitoring pro Nutzer oder Flow.

Zeitraum und Auflösung

Das Beispiel nutzt hours=48 und window_hours=4. Das ist ein Startpunkt, nicht die komplette Produktgrenze.

ZeitraumMit hours legst du den angefragten Horizont fest. Öffentlich belastbar kommunizieren wir für die Preisprognose aktuell maximal 120 Stunden.
Tatsächlich erlaubtOhne API-Key sind aktuell 48 Stunden frei. Mit Key kann mehr erlaubt sein, aber mehr als 120 Stunden Preisprognose sollten aktuell nicht als verlässliche öffentliche Zusage verstanden werden. Maßgeblich ist immer meta.allowed_horizon_hours.
AuflösungDay-Ahead kann in Viertelstunden kommen, Forecast und CO2 meist stündlich.

source.price.day_ahead_entries und source.price.forecast_entries zählen Slots, nicht Stunden. Deshalb können Zahlen wie 97 Day-Ahead und 0 Forecast plausibel sein, wenn der angefragte Zeitraum gerade schon fast vollständig mit veröffentlichten Day-Ahead-Werten abgedeckt ist.

Schnellstart für Copy-Paste

  1. In Node-RED oben rechts auf Import klicken.
  2. Den kompletten JSON-Block unten einfügen.
  3. Importieren und danach auf Deploy klicken.
  4. Die Debug-Seitenleiste öffnen und den Inject-Knopf einmal manuell auslösen.
Für den Start genugDer Flow zeigt bewusst erst einmal die wichtigsten Felder an, statt direkt eine komplexe Steuerlogik zu verstecken.
Was du ändern musstNormalerweise nur country=de in der URL und optional den API-Key im Function-Node.
Was du danach siehstmsg.current_price, msg.current_co2_g_kwh, aktive beste Fenster, nächste vollständige Zukunftsfenster und die wichtigsten Meta-Felder.

Import-Flow für Node-RED

Den gesamten Block kopieren und in Node-RED importieren. Wenn du keinen API-Key hast, bleibt der String im Function-Node einfach leer.

[
  {
    "id": "epf_tab",
    "type": "tab",
    "label": "StrompreisVorhersage",
    "disabled": false,
    "info": ""
  },
  {
    "id": "epf_inject",
    "type": "inject",
    "z": "epf_tab",
    "name": "Jetzt laden",
    "props": [],
    "repeat": "900",
    "once": true,
    "onceDelay": "1",
    "topic": "",
    "x": 120,
    "y": 120,
    "wires": [["epf_auth"]]
  },
  {
    "id": "epf_auth",
    "type": "function",
    "z": "epf_tab",
    "name": "API-Key optional",
    "func": "const API_KEY = \"\";\\nmsg.headers = {};\\nif (API_KEY.trim()) {\\n    msg.headers.Authorization = \"Bearer \" + API_KEY.trim();\\n}\\nreturn msg;",
    "outputs": 1,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 340,
    "y": 120,
    "wires": [["epf_http"]]
  },
  {
    "id": "epf_http",
    "type": "http request",
    "z": "epf_tab",
    "name": "Summary abrufen",
    "method": "GET",
    "ret": "obj",
    "paytoqs": "ignore",
    "url": "https://api.energypriceforecast.eu/api/v1/node-red/summary?country=de&hours=48&window_hours=4",
    "persist": false,
    "x": 570,
    "y": 120,
    "wires": [["epf_extract"]]
  },
  {
    "id": "epf_extract",
    "type": "function",
    "z": "epf_tab",
    "name": "Wichtige Felder setzen",
    "func": "const data = msg.payload || {};\\nconst flat = data.flat || {};\\nconst meta = data.meta || {};\\nconst price = data.price || {};\\nconst co2 = data.co2 || {};\\n\\nmsg.current_price = flat.current_price;\\nmsg.current_co2_g_kwh = flat.current_co2_g_kwh;\\nmsg.cheapest_window_start = flat.cheapest_window_start || null;\\nmsg.greenest_window_start = flat.greenest_window_start || null;\\nmsg.is_cheapest_window_now = flat.is_cheapest_window_now === true;\\nmsg.cheapest_window_remaining_minutes = flat.cheapest_window_remaining_minutes ?? null;\\nmsg.next_full_cheapest_window_start = price.next_full_window ? price.next_full_window.start : null;\\nmsg.is_greenest_window_now = flat.is_greenest_window_now === true;\\nmsg.next_full_greenest_window_start = co2.next_full_window ? co2.next_full_window.start : null;\\nmsg.api_key_state = meta.api_key_state || 'missing';\\nmsg.allowed_horizon_hours = meta.allowed_horizon_hours;\\nmsg.used_horizon_hours = meta.used_horizon_hours;\\nmsg.rate_limit_daily = meta.rate_limit_daily;\\nmsg.used_calls_today = meta.used_calls_today;\\n\\nif (msg.statusCode === 401) {\\n    msg.error = '401: API-Key fehlt, ist ungültig oder wurde deaktiviert.';\\n} else if (msg.statusCode === 403) {\\n    msg.error = '403: Zugriff für Route, Markt oder Vertragszustand nicht erlaubt.';\\n} else if (msg.statusCode === 429) {\\n    msg.error = '429: Tageslimit erreicht.';\\n} else {\\n    msg.error = null;\\n}\\n\\nreturn msg;",
    "outputs": 1,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 830,
    "y": 120,
    "wires": [["epf_debug"]]
  },
  {
    "id": "epf_debug",
    "type": "debug",
    "z": "epf_tab",
    "name": "Werte anzeigen",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "true",
    "targetType": "full",
    "x": 1070,
    "y": 120,
    "wires": []
  }
]

Danach kannst du anstelle des Debug-Knotens später eigene Logik anschließen, zum Beispiel Dashboard, Benachrichtigungen oder Scheduler-Regeln.

Für Automationen: Anzeige und Laufentscheidung trennen

Für Dashboards reicht oft msg.cheapest_window_start. Für echte Steuerung ist aber meist wichtiger, ob das beste Fenster bereits läuft. Genau dafür setzt der Flow zusätzlich msg.is_cheapest_window_now und msg.cheapest_window_remaining_minutes.

if (msg.is_cheapest_window_now) {
  // Verbraucher jetzt freigeben
} else if (msg.next_full_cheapest_window_start) {
  // nächstes vollständiges Fenster für Planung verwenden
}

return msg;

Pragmatisch: Ein Boolean für "jetzt" ist für Automationen meist wertvoller als nur ein Zeitstempel in der Zukunft.

Welche Message-Felder du danach hast

Feld Bedeutung Typischer Einsatz
msg.current_priceAktueller Preis in EUR/kWh.Einfache Preislogik oder Debug-Ausgabe.
msg.current_co2_g_kwhAktuelle CO2-Intensität.CO2-orientierte Steuerung.
msg.cheapest_window_startStartzeit des günstigsten zukünftigen Fensters.Spätere Timer- oder Scheduler-Logik.
msg.greenest_window_startStartzeit des CO2-ärmsten zukünftigen Fensters.Ökologische Lastverschiebung.
msg.is_cheapest_window_nowtrue, wenn das beste Preisfenster bereits läuft.Direkte Laufentscheidung für Verbraucher.
msg.cheapest_window_remaining_minutesRestlaufzeit des aktuell besten Preisfensters.Gerät nur so lange laufen lassen, wie das Fenster aktiv ist.
msg.next_full_cheapest_window_startStartzeit des nächsten vollständigen Preisfensters in der Zukunft.Planung statt Sofort-Trigger.
msg.api_key_stateStatus des verwendeten API-Keys.Sauberes Monitoring pro Nutzer oder Flow.
msg.allowed_horizon_hoursServerseitig erlaubter Maximalhorizont.Prüfen, ob ein Key mehr freischaltet.
msg.used_calls_todayHeute bereits verbrauchte Requests.Limits im Blick behalten.
msg.errorLesbarer Fehlertext bei 401, 403 oder 429.Direkte Fehlersuche im Debug.

Wichtige Hinweise

Ist das ein offizieller Node-RED-Node?

Nein. Es ist bewusst ein normaler Flow mit Standardknoten. Das ist für den Einstieg leichter nachvollziehbar und besser an eigene Automationen anpassbar.

Wie oft sollte ich abrufen?

Alle 15 Minuten sind ein sinnvoller Start. Die Summary ist kein Sekunden-Feed. Häufigeres Polling erhöht nur Last und Tagesverbrauch.

Was tun bei 401, 403 oder 429?

Der Flow schreibt dafür einen lesbaren Text in msg.error. 401 steht für Key-Probleme, 403 für einen nicht erlaubten Zugriff und 429 für ein erreichtes Tageslimit.

Was tun, wenn im Debug nichts Brauchbares ankommt?

Prüfe zuerst, ob der HTTP-Request wirklich als geparstes Objekt zurückkommt. Wenn statt JSON HTML ankommt, zeigt die URL wahrscheinlich auf den falschen Pfad oder eine fehlerhafte Zwischenadresse.

Kleine Testphase

Für die neue Node-RED-Anbindung läuft aktuell eine kleine Testphase. Gesucht sind vor allem echte Flows, bei denen schnell sichtbar wird, ob die importierbaren Beispiele verständlich sind und ob die Daten in realen Automationen sauber weiterverarbeitet werden können.

Wenn du Node-RED aktiv nutzt und das testen möchtest, schreib kurz mit deinem Setup und Markt an StrompreisVorhersage@proton.me. Die ersten Testeinbindungen werden bewusst noch manuell begleitet.

Verwandt: ioBroker, openHAB und Home Assistant.