Geocoder
Der Node löst Koordinaten zu Adressen auf (Reverse) oder Adressen zu Koordinaten (Forward) und nutzt dafür den Nominatim-Dienst von OpenStreetMap. Ein- und Ausgabefelder ordnen Sie frei per Punkt-Notation zu, sodass der Node sich in bestehende Payload-Strukturen einfügt. Anfragen werden serialisiert, zwischengespeichert und an das Ratenlimit der öffentlichen Nominatim-Instanz angepasst.
- Node-Typ
- geocoder
- Paket
- @htag/node-red-contrib-hypertegrity-utility
- Eingänge / Ausgänge
- 1 / 1
- Dienst
- Nominatim (OpenStreetMap), öffentlich oder eigene Instanz
Wofür Sie den Node verwenden
Viele Datenquellen liefern nur Koordinaten, andere nur Adressen. Der Geocoder ergänzt die jeweils fehlende Information, damit Entitäten in einer urbanen Datenplattform sowohl auf einer Karte dargestellt als auch nach Ort oder Straße durchsucht werden können.
Typische Einsatzfälle sind:
- Sensorstandorte beschriften: Ein stationärer Sensor meldet nur Breiten- und Längengrad. Der Node ergänzt Straße, Postleitzahl und Ort.
- Adresslisten auf die Karte bringen: Veranstaltungsorte, Haltestellen oder Einrichtungen liegen als Adresse vor und erhalten einen GeoJSON-Punkt für die
location-GeoProperty einer NGSI-LD-Entität. - Array-Payloads anreichern: Eine Liste von Objekten wird Eintrag für Eintrag aufgelöst, zum Beispiel vor der Übergabe an den NGSI-LD Builder.
So funktioniert der Node
Eingabe lesen
Der Node liest Koordinaten oder Adressfelder an den konfigurierten Pfaden, entweder aus der Nachricht oder aus jedem Eintrag eines Arrays.
Cache prüfen
Für jede Abfrage wird ein Cache-Schlüssel gebildet. Koordinaten werden dafür auf fünf Nachkommastellen (etwa 1 m) gerundet. Treffer werden ohne Anfrage beantwortet.
Nominatim anfragen
Fehlt ein Cache-Treffer, geht die Anfrage in eine Warteschlange, die den Mindestabstand zwischen zwei Anfragen einhält. Bei Antwortcode 429 oder 503 wird einmal nach 2 s wiederholt.
Ergebnis schreiben
Die Antwort wird in ein festes Feldset normalisiert und gemäß Feldzuordnung in die Nachricht beziehungsweise den Array-Eintrag geschrieben.
Ergebnis: Die ursprüngliche Nachricht, angereichert um Adress- oder Koordinatenfelder und optional um ein Status-Feld.
Der Node ist nachrichtengetrieben: Er wird nur aktiv, wenn eine Nachricht eingeht, und fragt Nominatim nicht von selbst ab. Im Modus Automatisch versucht er zuerst die Koordinaten-Zuordnung; nur wenn keine gültigen Koordinaten gefunden werden, greift die Adress-Zuordnung. Alle Anfragen eines Nodes laufen durch eine gemeinsame Warteschlange, unabhängig davon, wie viele Nachrichten gleichzeitig eintreffen.
Konfiguration
Der Bearbeitungsdialog ist in die Registerkarten Allgemein, Eingabe, Ausgabe, Dienst und Test gegliedert. Das Feld Name steht oberhalb der Registerkarten.
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Name | Text | leer | Anzeigename des Nodes im Flow. |
Registerkarte Allgemein
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Modus | Auswahl | Koordinaten → Adresse (Reverse) | reverse löst Koordinaten zu einer Adresse auf, forward eine Adresse zu Koordinaten, auto probiert zuerst Koordinaten und dann die Adresse. |
| Verarbeiten | Auswahl | Einzelne Nachricht | message: alle Pfade sind relativ zu msg, zum Beispiel payload.lat. array: jeder Eintrag des Arrays wird einzeln aufgelöst, Pfade sind relativ zum Eintrag, zum Beispiel location.lat. |
| Array-Pfad | Text | payload | Nur bei Verarbeiten = Array-Einträge: Pfad des Arrays relativ zu msg. |
| Bei Fehler | Auswahl | Nachricht weitergeben (Warnung loggen) | Verhalten bei Anfragefehlern: pass gibt die Nachricht weiter und loggt eine Warnung, drop verwirft die Nachricht (auch bei Abfragen ohne Ergebnis, sofern nichts aufgelöst wurde), error löst einen Node-Fehler aus, den ein Catch-Node abfangen kann. |
Registerkarte Eingabe
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Beispiel JSON | Textfeld | leer | Beispiel-Payload zum Erkennen von Pfaden. Die gefundenen Pfade werden in allen Pfadfeldern als Vorschläge angeboten; freie Eingabe bleibt möglich. |
| Format | Auswahl | Getrennte Felder (lat / lon) | Koordinatenquelle für Reverse: separate (zwei Felder), array (Koordinaten-Array) oder geojson (Objekt mit coordinates-Array in der Reihenfolge [lon, lat], zum Beispiel der Wert einer NGSI-LD GeoProperty). |
| Breitengrad-Feld | Pfad | leer | Pfad zum Breitengrad bei Format „Getrennte Felder“. |
| Längengrad-Feld | Pfad | leer | Pfad zum Längengrad bei Format „Getrennte Felder“. |
| Array-Feld | Pfad | leer | Pfad zum Koordinaten-Array bei Format „Koordinaten-Array“. |
| Koordinatenreihenfolge | Auswahl | [Längengrad, Breitengrad] | Reihenfolge der Werte im Koordinaten-Array: lonlat (GeoJSON-Standard) oder latlon. |
| GeoJSON-Feld | Pfad | leer | Pfad zum GeoJSON-Point-Objekt bei Format „GeoJSON-Point-Objekt“. |
| Abfrageart | Auswahl | Freitext (ein Feld) | Adressquelle für Forward: free (ein Feld mit der vollständigen Adresse) oder structured (einzelne Felder). |
| Adress-Feld | Pfad | leer | Pfad zum Freitextfeld mit der vollständigen Adresse. |
| Straße, Hausnummer, Postleitzahl, Ort, Kreis / Bezirk, Bundesland, Land | Pfad | leer | Pfade für die strukturierte Abfrage. Nur gefüllte Felder werden gesendet. Straße und Hausnummer werden zu einem Nominatim-Parameter street zusammengefasst. |
Alle Felder dieser Registerkarte werden gemeinsam in der Node-Eigenschaft inputConfig gespeichert.
Registerkarte Ausgabe
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Feldzuordnung | Liste | Vorlage Adresse | Je Zeile ein Ergebnisfeld (links) und der Zielpfad, in den es geschrieben wird (rechts). Vorhandene Werte werden überschrieben. Die Liste wird in outputMappings gespeichert. |
| Vorlage Adresse | Schaltfläche | – | Füllt die Zuordnung mit displayName → payload.address, street → payload.street, houseNumber → payload.houseNumber, postalCode → payload.postalCode, city → payload.city und countryCode → payload.countryCode. |
| Vorlage Koordinaten | Schaltfläche | – | Füllt die Zuordnung mit lat → payload.lat, lon → payload.lon, geoPoint → payload.location und displayName → payload.address. |
| Gesamtergebnis nach | Pfad | leer (aus) | Optionaler Pfad, in den das vollständige normalisierte Ergebnis geschrieben wird, zum Beispiel payload.geocode. |
| Status nach | Pfad | leer (aus) | Optionaler Pfad für den Status ok, notFound, noInput oder error, zum Beispiel payload.geocodeStatus. Eignet sich zum Routen mit einem Switch-Node. |
| Leere Felder als null schreiben | Kontrollkästchen | inaktiv | Schreibt nicht aufgelöste Felder (und das Gesamtergebnis) als null, statt sie zu überspringen. |
Registerkarte Dienst
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
| Endpunkt | Text | siehe unten | Basis-URL des Nominatim-Dienstes. Abschließende Schrägstriche werden entfernt. Eine eigene Instanz ist hier einzutragen. |
| Sprache | Text | de | Wird als Parameter accept-language gesendet und bestimmt die Sprache der Adressfelder. |
| Detailgrad (Zoom) | Zahl 0–18 | 18 | Nur für Reverse: 18 liefert Hausnummerngenauigkeit, 10 etwa Ortsebene, 8 Kreisebene. |
| Kontakt-E-Mail | Text | leer | Wird als Parameter email mitgesendet. Die Nominatim-Nutzungsrichtlinie erwartet eine Kontaktadresse bei höherem Volumen. |
| User-Agent | Text | leer | HTTP-Header User-Agent. Leer bedeutet Node-RED-Hypertegrity-Geocoder. Die Nutzungsrichtlinie verlangt einen aussagekräftigen, anwendungsspezifischen User-Agent. |
| Mindestabstand (ms) | Zahl | 1100 | Mindestzeit zwischen zwei Anfragen dieses Nodes. Der Standard hält das Limit von einer Anfrage pro Sekunde der öffentlichen Instanz ein. |
| Cache-Lebensdauer (s) | Zahl | 86400 | Gültigkeitsdauer eines Cache-Eintrags (24 h). 0 bedeutet unbegrenzt gültig. |
| Cache-Einträge | Zahl | 500 | Maximale Zahl der Einträge im Arbeitsspeicher-Cache; der älteste Eintrag fällt heraus. 0 deaktiviert den Cache. |
| Cache leeren | Schaltfläche | – | Leert den Cache des deployten Nodes über den Admin-Endpunkt POST /geocoder/<Node-ID>/cache/clear. |
Standardwerte der URL-Felder:
Endpunkt: https://nominatim.openstreetmap.org
Registerkarte Test
Die Registerkarte speichert keine Einstellungen. Sie führt eine Beispielabfrage (Koordinaten oder Adresse) über das Node-RED-Backend aus, zeigt die gefundenen Ergebnisfelder und das normalisierte JSON an und übernimmt einzelne Felder per Klick in die Feldzuordnung. Der Test nutzt Endpunkt, Sprache, Detailgrad und Kontakt-E-Mail der Registerkarte Dienst.
Fügen Sie auf der Registerkarte Eingabe eine echte Payload ein. Danach bieten alle Pfadfelder die erkannten Pfade als Auswahl an, und Tippfehler in Pfaden werden vermieden.
Eingang
Der Node wertet die Nachricht ausschließlich über die konfigurierten Pfade aus. Es gibt keine Steuerbefehle.
| Eigenschaft | Typ | Bedeutung |
|---|---|---|
msg.payload | Objekt | Bei Verarbeiten = Einzelne Nachricht: Objekt mit den konfigurierten Quellfeldern. Die Pfade sind relativ zu msg, daher beginnen sie üblicherweise mit payload.. |
msg.<Array-Pfad> | Array von Objekten | Bei Verarbeiten = Array-Einträge: jedes Element wird einzeln aufgelöst. Elemente, die kein Objekt sind, erhalten den Status noInput. Ist der Pfad kein Array, meldet der Node den Fehler msg.<Array-Pfad> is not an array. |
| Koordinatenfelder | Zahl oder numerischer Text | Breitengrad zwischen -90 und 90, Längengrad zwischen -180 und 180. Ungültige Werte gelten als nicht vorhanden. |
| Adressfelder | Text | Freitextfeld oder strukturierte Einzelfelder; leere Werte werden ignoriert. |
Ausgang
Der Node gibt die Eingangsnachricht weiter und schreibt die zugeordneten Felder hinein. Mit der Vorlage Adresse und Reverse-Modus sieht msg.payload zum Beispiel so aus:
{
"lat": 50.0,
"lon": 8.353,
"address": "12, Musterstraße, Beispielstadt, Beispielkreis, Hessen, 65239, Deutschland",
"street": "Musterstraße",
"houseNumber": "12",
"postalCode": "65239",
"city": "Beispielstadt",
"countryCode": "DE"
}
Beide Richtungen liefern denselben normalisierten Satz an Ergebnisfeldern, aus dem Sie in der Feldzuordnung wählen:
| Feld | Bedeutung |
|---|---|
displayName | Vollständige Adresse als Text (display_name von Nominatim). |
name | Name des getroffenen OSM-Objekts, zum Beispiel ein POI- oder Straßenname. |
addressLine | Straße und Hausnummer in einem Feld. |
street | Straße (aus road, pedestrian, footway, path oder street). |
houseNumber | Hausnummer. |
postalCode | Postleitzahl. |
city | Ort (aus city, town, village, municipality oder hamlet). |
suburb | Stadtteil (aus suburb, city_district, borough oder neighbourhood). |
county | Kreis oder Bezirk. |
state | Bundesland oder Region. |
country | Land. |
countryCode | Ländercode in Großbuchstaben, zum Beispiel DE. |
lat, lon | Koordinaten als Zahl. |
geoPoint | GeoJSON-Point {"type": "Point", "coordinates": [lon, lat]}, direkt als NGSI-LD-GeoProperty-Wert verwendbar. |
boundingBox | Begrenzungsrahmen als Zahlen-Array. |
osmId, osmType, placeId | Kennungen des OSM-Objekts. |
category, type, addressType | Klassifizierung des Objekts durch Nominatim. |
address | Unverändertes Adress-Objekt der Antwort. |
raw | Vollständige, unveränderte Antwort. |
Felder ohne Wert werden übersprungen, sofern Leere Felder als null schreiben nicht aktiv ist. Bei Forward-Abfragen wird nur das erste Ergebnis verwendet (limit=1).
Beispiel-Flow
Das Paket bringt einen Beispiel-Flow mit. Sie importieren ihn in Node-RED über Menü → Importieren → Beispiele → @htag/node-red-contrib-hypertegrity-utility → geocoder. Alternativ laden Sie die Datei geocoder.json herunter und importieren sie über Menü → Importieren.
Inject und Function
Ein Inject-Node startet zwei Function-Nodes: eine erzeugt ein Koordinatenpaar, die andere eine Adresse.
Geocoder
Ein Geocoder im Reverse-Modus ergänzt Adressfelder, ein zweiter im Forward-Modus einen GeoJSON-Punkt.
Debug
Zwei Debug-Nodes zeigen die angereicherten Payloads in der Seitenleiste an.
Beispiel-Flow als JSON anzeigen
[
{"id": "tab1", "type": "tab", "label": "geocoder", "disabled": false, "info": ""},
{"id": "inject1", "type": "inject", "z": "tab1", "name": "", "props": [{"p": "payload"}], "repeat": "", "once": false, "payload": "", "payloadType": "date", "x": 120, "y": 140, "wires": [["fn1", "fn2"]]},
{"id": "fn1", "type": "function", "z": "tab1", "name": "input1", "func": "msg.payload = { lat: 50.000, lon: 8.353 };\nreturn msg;", "outputs": 1, "x": 270, "y": 140, "wires": [["geo1"]]},
{"id": "geo1", "type": "geocoder", "z": "tab1", "name": "", "mode": "reverse", "scope": "message", "arrayPath": "payload", "sampleJson": "{\"lat\":50,\"lon\":8.353}",
"inputConfig": "{\"posType\":\"separate\",\"order\":\"lonlat\",\"latField\":\"payload.lat\",\"lonField\":\"payload.lon\",\"queryMode\":\"free\"}",
"outputMappings": "[{\"field\":\"displayName\",\"target\":\"payload.address\"},{\"field\":\"street\",\"target\":\"payload.street\"},{\"field\":\"houseNumber\",\"target\":\"payload.houseNumber\"},{\"field\":\"postalCode\",\"target\":\"payload.postalCode\"},{\"field\":\"city\",\"target\":\"payload.city\"},{\"field\":\"countryCode\",\"target\":\"payload.countryCode\"}]",
"resultProperty": "", "statusProperty": "", "writeMissing": false, "onError": "pass",
"endpoint": "https://nominatim.openstreetmap.org", "language": "de", "email": "kontakt@beispiel.de", "userAgent": "Beispielstadt-Nodered",
"zoom": 18, "minInterval": 1100, "cacheTtl": 86400, "cacheSize": 500, "x": 440, "y": 140, "wires": [["dbg1"]]},
{"id": "dbg1", "type": "debug", "z": "tab1", "name": "Adresse", "active": true, "tosidebar": true, "complete": "payload", "targetType": "msg", "x": 620, "y": 140, "wires": []},
{"id": "fn2", "type": "function", "z": "tab1", "name": "input2", "func": "msg.payload = { address: \"Musterstraße, Beispielstadt, 65239, Deutschland\" };\nreturn msg;", "outputs": 1, "x": 270, "y": 200, "wires": [["geo2"]]},
{"id": "geo2", "type": "geocoder", "z": "tab1", "name": "", "mode": "forward", "scope": "message", "arrayPath": "payload", "sampleJson": "",
"inputConfig": "{\"posType\":\"separate\",\"order\":\"lonlat\",\"queryMode\":\"free\",\"queryField\":\"payload.address\"}",
"outputMappings": "[{\"field\":\"geoPoint\",\"target\":\"payload.location\"}]",
"resultProperty": "", "statusProperty": "", "writeMissing": false, "onError": "pass",
"endpoint": "https://nominatim.openstreetmap.org", "language": "de", "email": "kontakt@beispiel.de", "userAgent": "Beispielstadt-Nodered",
"zoom": 18, "minInterval": 1100, "cacheTtl": 86400, "cacheSize": 500, "x": 440, "y": 200, "wires": [["dbg2"]]},
{"id": "dbg2", "type": "debug", "z": "tab1", "name": "Koordinaten", "active": true, "tosidebar": true, "complete": "payload", "targetType": "msg", "x": 630, "y": 200, "wires": []}
]
Status und Fehler
Der Status zeigt laufende Zähler: ok = aufgelöste Abfragen, err = fehlgeschlagene Anfragen, cache = aus dem Cache beantwortete Abfragen.
| Anzeige | Bedeutung |
|---|---|
| Grauer Ring „ready“ | Node ist deployt, noch keine Nachricht verarbeitet. |
| Blauer Ring „5 items“ | Ein Array mit fünf Einträgen wird gerade abgearbeitet. |
| Grüner Punkt „3 ok · 1 cache“ | Alle Einträge der letzten Nachricht wurden aufgelöst. |
| Gelber Ring „2 unresolved · 3 ok“ | Zwei Einträge ohne Ergebnis (notFound) oder ohne verwertbare Eingabe (noInput); die Nachricht wurde weitergegeben. |
| Gelber Ring „unresolved · …“ | Bei Fehler = Nachricht verwerfen: nichts aufgelöst, die Nachricht wurde verworfen. |
| Roter Ring „error · 2 ok · 1 err“ | Mindestens eine Anfrage ist fehlgeschlagen (Netzwerk, Zeitüberschreitung nach 15 s, HTTP-Fehler). |
| Roter Ring „msg.payload is not an array · …“ | Der Array-Pfad zeigt nicht auf ein Array. Dieser Fehler wird immer als Node-Fehler gemeldet, unabhängig von der Einstellung Bei Fehler. |
Warnungen und Fehler im Protokoll:
Nominatim responded 429 (rate limit / unavailable) — retrying once in 2000 ms.: Warnung vor dem einmaligen Wiederholungsversuch.Geocoding failed for '<Koordinaten oder Abfrage>': <Ursache>: bei Nachricht weitergeben und Nachricht verwerfen als Warnung, bei Node-Fehler auslösen als Fehler übernode.error, abfangbar mit einem Catch-Node. Bei mehreren Fehlern lautet die Meldung<n> lookups failed, first: ….
„Kein Ergebnis“ und „keine Eingabe“ lösen nie einen Fehler aus; sie sind nur über das Status-Feld und die Statusanzeige erkennbar.
Hinweise
- Nominatim-Nutzungsbedingungen: Die öffentliche Instanz erlaubt maximal eine Anfrage pro Sekunde, verlangt einen anwendungsspezifischen User-Agent und untersagt Massen-Geocoding. Der Node berücksichtigt das durch den Mindestabstand von 1100 ms, die Warteschlange, den Cache, den einmaligen Wiederholungsversuch bei 429/503 sowie die Felder User-Agent und Kontakt-E-Mail. Tragen Sie beide Felder mit eigenen Werten ein. Für regelmäßige oder große Datenmengen betreiben Sie eine eigene Nominatim-Instanz und tragen sie als Endpunkt ein.
- Testabfragen im Editor werden direkt ausgeführt. Vermeiden Sie viele Tests kurz hintereinander gegen die öffentliche Instanz.
- Cache nur im Arbeitsspeicher: Der Cache gehört zur Node-Instanz und wird bei Deploy, Neustart oder über Cache leeren gelöscht. Ein persistenter Kontextspeicher ist nicht beteiligt.
- Array-Verarbeitung dauert: Pro Eintrag entsteht eine Anfrage. Ein Array mit 100 neuen Orten benötigt bei 1100 ms Mindestabstand rund zwei Minuten.
- Proxy: Der Node bietet keine eigene Proxy-Einstellung. In abgeschotteten Netzen empfiehlt sich eine eigene Nominatim-Instanz im internen Netz.
- Datenschutz: Adressen und genaue Koordinaten können personenbezogene Daten im Sinne der DSGVO sein, etwa bei Wohnadressen oder Standorten einzelner Personen. Jede Abfrage übermittelt den Ort an den konfigurierten Dienst, beim öffentlichen Endpunkt an einen Dritten außerhalb Ihrer Infrastruktur. Verwenden Sie für personenbezogene Daten eine eigene Nominatim-Instanz, wählen Sie den Detailgrad nicht höher als nötig und prüfen Sie, ob die Verarbeitung durch den Zweck gedeckt ist.
- Einheiten: Koordinaten sind Dezimalgrad (WGS 84); GeoJSON verwendet die Reihenfolge
[Längengrad, Breitengrad].