Post to Stellio
Der Node sendet ein Array von NGSI-LD-Entitäten per HTTP POST an den Batch-Upsert-Endpunkt des Stellio Context Brokers. Neue Entitäten werden angelegt, vorhandene aktualisiert. Statuscode, Antwort-Header und Antwortkörper stehen anschließend in der Nachricht zur Verfügung.
- Node-Typ
- post-to-stellio
- Paket
- @htag/node-red-contrib-hypertegrity-ngsi-ld
- Eingänge / Ausgänge
- 1 / 1
- Ziel
- Stellio Context Broker (NGSI-LD)
Wofür Sie den Node verwenden
Post to Stellio ist der letzte Schritt des typischen Datenflusses: Nachdem der NGSI-LD Builder aus den Connector-Daten normalisierte Entitäten erzeugt hat, schreibt dieser Node sie in den Context Broker. Er nutzt den Endpunkt entityOperations/upsert mit der Option update, sodass bestehende Entitäten attributweise aktualisiert und neue angelegt werden, ohne dass Sie vorher prüfen müssen, ob eine Entität existiert.
Typische Einsatzfälle sind:
- Regelmäßige Messwerte (Wetter, Luftqualität, Pegel) fortlaufend in denselben Entitäten aktualisieren.
- Stammdaten wie Parkplätze, Haltestellen oder Sehenswürdigkeiten einmalig oder nach Änderungen einspielen.
- Mehrere Datenräume (Tenants) aus einem Flow beliefern, indem der Tenant je Nachricht über
msg.tenantgesetzt wird.
So funktioniert der Node
Nachricht empfangen
msg.payload enthält das Entitäten-Array, zum Beispiel direkt vom NGSI-LD Builder.
Ziel bestimmen
API-URL und Tenant werden aus msg, Node-Konfiguration oder der Umgebungsvariable STELLIO_API_URL ermittelt.
POST senden
Der Payload geht als application/ld+json an /ngsi-ld/v1/entityOperations/upsert?options=update.
Antwort weitergeben
Statuscode, Header und Antwortkörper werden in die Nachricht geschrieben und ausgegeben.
Ergebnis: Die Entitäten liegen im Broker; die Nachricht trägt die Broker-Antwort für Fehlerbehandlung und Protokollierung.
Der Node ist nachrichtenbasiert und sendet jede eingehende Nachricht sofort als eigenen HTTP-Request. Bei großen Datenmengen empfiehlt sich davor ein Split-Node mit Paketen zu wenigen Entitäten und ein Delay-Node zur Ratenbegrenzung, wie im Beispiel-Flow gezeigt.
Konfiguration
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Name | Text | leer | Anzeigename des Nodes im Flow. |
| Tenant | Text (Pflicht) | leer | Wert des Headers NGSILD-Tenant, also der Datenraum im Broker, zum Beispiel ds_opendata. |
| Stellio API URL | Text | ${STELLIO_API_URL} | Basis-URL des Brokers ohne Pfad /ngsi-ld/v1. Der Platzhalter wird von Node-RED aus der gleichnamigen Umgebungsvariable ersetzt. Bleibt das Feld leer, verwendet der Node STELLIO_API_URL aus der Umgebung. |
Die API-URL ist optional, weil die Umgebungsvariable STELLIO_API_URL als Rückfallwert dient. Ohne gültige URL bricht der Node mit einem Fehler ab.
Eingang
| Eigenschaft | Typ | Bedeutung |
|---|---|---|
msg.payload | Array von Entitäten | Wird unverändert als JSON gesendet. Der Batch-Upsert-Endpunkt erwartet ein Array; der NGSI-LD Builder liefert immer ein Array. Jede Entität muss id, type und @context enthalten, da der Node keinen Link-Header setzt. Fehlt der Payload, wird ein leeres Objekt gesendet. |
msg.tenant | Text | Überschreibt den konfigurierten Tenant für diese Nachricht. |
msg.stellioApiUrl | Text | Überschreibt die konfigurierte API-URL für diese Nachricht. |
Ausgang
Die eingehende Nachricht wird um die Antwort des Brokers ergänzt. Bei einem Batch-Upsert, in dem eine Entität neu angelegt und eine aktualisiert wurde, sieht die Ausgabe zum Beispiel so aus:
{
"statusCode": 201,
"headers": {
"content-type": "application/json",
"date": "Thu, 01 Oct 2026 06:00:02 GMT"
},
"payload": [
"urn:ngsi-ld:WeatherObserved:beispielstadt:station-042"
]
}
| Feld | Bedeutung |
|---|---|
msg.statusCode | HTTP-Statuscode der Antwort. 201 meldet neu angelegte Entitäten (ihre IDs stehen im Payload), 204 eine reine Aktualisierung ohne Inhalt, 207 ein Teilergebnis mit Erfolgen und Fehlern. |
msg.headers | Alle Antwort-Header des Brokers. |
msg.payload | Antwortkörper als geparstes JSON. Ist die Antwort kein JSON, bleibt der Rohtext erhalten; bei leerer Antwort ist der Wert null. Das ursprüngliche Entitäten-Array wird dabei ersetzt. |
Der Node sendet die Nachricht auch bei Fehlerstatus wie 400 oder 500 weiter. Prüfen Sie msg.statusCode in einem Switch-Node, wenn Sie fehlgeschlagene Übertragungen gesondert behandeln möchten.
Beispiel-Flow
Das Paket bringt einen gemeinsamen Beispiel-Flow für mehrere Stellio-Nodes mit. Sie importieren ihn in Node-RED über Menü → Importieren → Beispiele → @htag/node-red-contrib-hypertegrity-ngsi-ld → stellio-helper-nodes. Alternativ laden Sie die Datei stellio-helper-nodes.json herunter und importieren sie über Menü → Importieren.
Daten erzeugen
Inject, Function, Split und Delay liefern Luftqualitäts-Datensätze in kleinen, gedrosselten Paketen.
NGSI Builder
Der Builder formt jedes Paket in AirQualityObserved-Entitäten um.
Post to Stellio
Der Node schreibt das Entitäten-Array per Upsert in den Tenant des Brokers.
Beispiel-Flow als JSON anzeigen (Ausschnitt Post to Stellio)
[
{"id": "tab1", "type": "tab", "label": "Stellio Helper Nodes", "disabled": false, "info": ""},
{"id": "inject1", "type": "inject", "z": "tab1", "name": "", "props": [{"p": "payload"}], "repeat": "", "once": false, "payload": "", "payloadType": "date", "x": 160, "y": 580, "wires": [["func1"]]},
{"id": "func1", "type": "function", "z": "tab1", "name": "Luftqualität", "func": "msg.payload = [\n {\"id\": \"urn:ngsi-ld:AirQualityObserved:beispielkreis:2026-09-30\", \"type\": \"AirQualityObserved\", \"dateObserved\": \"2026-09-30T00:00:00Z\", \"location\": {\"type\": \"Point\", \"coordinates\": [7.3322, 50.3315]}, \"areaServed\": \"Beispielkreis\", \"temperature\": 9.8, \"o3\": 0.1239}\n];\nreturn msg;", "outputs": 1, "x": 350, "y": 580, "wires": [["split1"]]},
{"id": "split1", "type": "split", "z": "tab1", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": "5", "arraySpltType": "len", "stream": false, "property": "payload", "x": 570, "y": 580, "wires": [["delay1"]]},
{"id": "delay1", "type": "delay", "z": "tab1", "name": "", "pauseType": "rate", "timeout": "5", "timeoutUnits": "seconds", "rate": "1", "nbRateUnits": "2", "rateUnits": "second", "drop": false, "x": 140, "y": 700, "wires": [["builder1"]]},
{"id": "builder1", "type": "ngsi-builder", "z": "tab1", "name": "", "contextUrl": "https://context.${DOMAIN}/main-context", "entityType": "AirQualityObserved", "mode": "smart", "entityId": "", "addObservedAt": true,
"mappings": [
{"target": "id", "source": "id", "addObservedAt": true, "required": true},
{"target": "type", "source": "type", "addObservedAt": true, "required": true},
{"target": "dateObserved", "source": "dateObserved", "addObservedAt": true, "required": true},
{"target": "location", "source": "location.coordinates", "addObservedAt": true, "required": true},
{"target": "areaServed", "source": "areaServed", "addObservedAt": true, "required": false},
{"target": "temperature", "source": "temperature", "addObservedAt": true, "required": false},
{"target": "o3", "source": "o3", "addObservedAt": true, "required": false}
],
"customFields": [], "customMappings": [], "overwrites": [], "debugMode": false, "useTransformation": false, "transformationScript": "", "topicFilter": "", "useObservedAtOverwrite": false, "observedAtField": "", "ignoreRequired": false, "enableValidation": true, "invalidExtraFields": false, "invalidMissingOptional": false, "invalidValue": false, "invalidOptionalAction": "skip",
"locationConfig": {"enabled": true, "type": "Point", "posType": "array", "latField": "", "lonField": "", "arrayField": "location.coordinates", "polyField": "", "order": "lonlat"},
"x": 380, "y": 700, "wires": [["post1"]]},
{"id": "post1", "type": "post-to-stellio", "z": "tab1", "name": "", "stellioApiUrl": "${STELLIO_API_URL}", "tenant": "ds_opendata", "x": 590, "y": 700, "wires": [[]]}
]
Status und Fehler
Der Node zeigt keinen Status unter dem Node-Symbol an. Fehler werden über node.error gemeldet und können mit einem Catch-Node abgefangen werden.
| Anzeige | Bedeutung |
|---|---|
| Fehler „Stellio API URL is required“ | Weder msg.stellioApiUrl, noch das Feld Stellio API URL, noch die Umgebungsvariable STELLIO_API_URL ist gesetzt. Die Nachricht wird nicht gesendet. |
| Fehler mit Netzwerkmeldung (zum Beispiel „ECONNREFUSED“, „ENOTFOUND“) | Der Broker ist nicht erreichbar oder der Hostname kann nicht aufgelöst werden. Die Nachricht wird nicht weitergegeben. |
msg.statusCode 201 / 204 / 207 | Erfolgreicher Upsert: angelegt, aktualisiert oder teilweise erfolgreich. |
msg.statusCode 400 | Der Broker lehnt den Payload ab, zum Beispiel wegen fehlendem @context, ungültiger URN oder fehlerhaftem JSON-LD. Details stehen in msg.payload. |
msg.statusCode 401 / 403 | Zugriff verweigert. Prüfen Sie die Absicherung durch Netzwerk oder vorgeschaltetes Gateway. |
msg.statusCode 404 | Der Pfad /ngsi-ld/v1/entityOperations/upsert wurde nicht gefunden; prüfen Sie die Basis-URL. |
Hinweise
- Kein Link-Header: Der Node sendet
Content-Type: application/ld+json. Der@contextmuss daher in jeder Entität enthalten sein, wie es der NGSI-LD Builder sicherstellt. - Authentifizierung: Der Node sendet keine Authentifizierungs-Header; der Zugriff auf den Broker wird über das Netzwerk oder ein vorgeschaltetes Gateway geschützt.
- Ratenbegrenzung: Jede Nachricht ist ein Request. Kombinieren Sie Split- und Delay-Node, um den Broker bei Massenimporten nicht zu überlasten.
- Payload wird ersetzt: Nach dem Senden enthält
msg.payloaddie Broker-Antwort, nicht mehr die Entitäten. Legen Sie die Entitäten vorher in einer anderen Eigenschaft ab, wenn Sie sie später noch benötigen. - Personenbezogene Daten: Der Node überträgt alle Inhalte unverändert in den Broker. Prüfen Sie vorab, ob die Entitäten personenbezogene Daten enthalten und ob der Ziel-Tenant dafür freigegeben ist.