Skip to main content
Utility

Location Group

The node checks which of the configured areas a point lies in, for example which municipality or district. You search the areas in the editor via OpenStreetMap Nominatim and assign them to group names. At runtime the node writes the group name into an output property or lets only messages pass that lie inside an area. The check runs locally with Turf.js, without any request to a service.

  • Area assignment
  • Point-in-polygon
  • Filter
Node type
location-group
Package
@htag/node-red-contrib-hypertegrity-utility
Inputs / outputs
1 / 1
Dependency
@turf/boolean-point-in-polygon; Nominatim only in the editor

When to use this node​

In a regional data platform, readings often originate from several municipalities or districts. The Location Group node assigns each data point to an area based on its coordinates, without you having to maintain polygons yourself: boundaries are loaded directly from OpenStreetMap into the node.

Typical use cases are:

  • Grouping data points by municipality: Sensors of a network receive the property locationGroup so that dashboards can filter by municipality.
  • Restricting data streams to an area: Only vehicles, measurements or reports inside your own city limits are processed further.
  • Combining several areas into one group: Several districts or municipalities share one group name, for example for a service area.

How the node works​

1

Define areas

In the editor you search administrative boundaries via Nominatim or click on the map. The polygons are stored with the flow configuration.

2

Read coordinates

At runtime the node reads latitude and longitude or a coordinate array at the configured paths, for every message or every array entry.

3

Test point against polygons

Turf.js checks locally whether the point lies inside one of the polygons. The first matching area wins.

4

Enrich or filter

Depending on the mode the group name is written into the output property or the message or array entry is dropped.

Result: Messages or array entries with a normalized group name, or only those entries that lie inside a configured area.

The node is message-driven and works entirely locally at runtime. Nominatim is queried only in the editor when searching for areas. If no areas are configured, the node forwards every message unchanged. The group name is normalized: umlauts are transcribed (ä → ae, ß → ss), spaces become _ and all characters other than letters, digits and _ are removed. Without a match the value is unknown.

Configuration​

The edit dialog consists of the tabs Regions, Settings and Data Discovery. The Name field sits above the tabs.

FieldTypeDefaultMeaning
NameTextemptyDisplay name of the node in the flow.

Regions tab​

FieldTypeDefaultMeaning
Search OSM BoundariesSearch fieldemptySearches Nominatim for areas through the admin endpoint /location-group/search (up to 10 hits). Only hits with a Polygon or MultiPolygon are listed. + adds the area to the list.
Selected RegionsListemptyOne row per area with Group (freely editable, default: first part of the Nominatim name) and Area (full name, read-only). Several areas may share the same group name. The list, including the polygon, is stored in the node property regions.
Map PreviewMap–Leaflet map showing all stored polygons. Clicking the map queries the administrative hierarchy at that position via /location-group/find-at (zoom levels 8, 10 and 14, that is district, municipality and suburb) and offers the boundaries found for adoption.

Settings tab​

FieldTypeDefaultMeaning
ModeSelectEnrich (Append Property)enrich writes the group name or unknown into the output property. filter lets only messages or array entries pass that lie inside an area.
Also enrich passing messagesCheckboxdisabledFilter mode only: additionally writes the group name into the output property.
Invert Filter (Keep Unknowns)CheckboxdisabledFilter mode only: keeps only messages that lie in no area.
Output PropertyTyped input (msg)locationGroupPath the group name is written to. Relative to msg for single objects, relative to each entry for arrays (see Output).

Data Discovery tab​

FieldTypeDefaultMeaning
Sample JSONText areaemptySample payload (object or array). Auto-Detect Settings looks for a GeoJSON Point, an object with lat/lon or a pair of numbers and proposes the field paths; Apply to Form adopts them. The detected paths also serve as suggestions in the path fields.
Geo TypeSelectPointGeometry type of the input data: Point, LineString, Polygon, MultiPoint, MultiLineString or MultiPolygon. Point geometries are evaluated.
Position TypeSelectSeparate Lat/Lon FieldsFor Geo Type Point: separate (two fields) or array (coordinate array).
Latitude FieldPathemptyPath to the latitude, for example location.coordinates[1].
Longitude FieldPathemptyPath to the longitude, for example location.coordinates[0].
Array FieldPathemptyPath to the coordinate array, for example location.coordinates.
GeoJSON FieldPathemptyFor other Geo Types: path to the coordinates array of the geometry.
Coord OrderSelectLongitude, LatitudeOrder in the coordinate array: lonlat (GeoJSON default) or latlon.
Preview MapMap–Shows the position read from the sample JSON and reports invalid or missing coordinates.

Geo Type, Position Type, Latitude/Longitude Field, Array Field, GeoJSON Field and Coord Order are stored together in the node property locationConfig.

Paths for single objects

Paths are evaluated relative to msg.payload by default. If the latitude or array field path starts with payload, the node evaluates relative to msg; if it starts with msg., relative to the message object. For arrays, paths are always relative to the individual entry.

Input​

PropertyTypeMeaning
msg.payloadobjectSingle data point. The configured paths are read relative to msg.payload (exceptions see note above).
msg.payloadarray of objectsList of data points. Every entry is checked individually; paths are relative to the entry.
Coordinate fieldsnumber or numeric stringLatitude and longitude in decimal degrees, or an array with at least two numbers in the configured order.

Without configured regions every message is forwarded unchanged.

Output​

In Enrich mode with an array in msg.payload the output looks like this:

[
{
"id": "urn:ngsi-ld:WeatherObserved:station-01",
"location": {"type": "Point", "coordinates": [8.6, 49.5]},
"locationGroup": "Exampletown"
},
{
"id": "urn:ngsi-ld:WeatherObserved:station-02",
"location": {"type": "Point", "coordinates": [9.9, 50.8]},
"locationGroup": "unknown"
}
]
FieldMeaning
<output property> on every array entryNormalized group name of the first matching area or unknown. Set with dot notation relative to the entry; intermediate objects are created.
msg.<output property> for a single objectFor a single object the output property is set via RED.util.setMessageProperty relative to msg. With the default locationGroup this yields msg.locationGroup; for a value inside the payload enter payload.locationGroup.
msg.payloadIn Filter mode the array contains only the entries that passed; a single message without a match is not sent at all. With Invert Filter only entries without a match remain; if Also enrich passing messages is enabled as well, they receive the value unknown.

Example flow​

The package ships with an example flow. Import it in Node-RED via Menu → Import → Examples → @htag/node-red-contrib-hypertegrity-utility → location-group. Alternatively download location-group.json and import it via Menu → Import. The file contains the complete municipality polygon from OpenStreetMap and is therefore large.

Step 1

Inject and Function

An Inject node triggers a Function that produces an array with one NGSI-LD-like entity including a GeoJSON point.

Step 2

Location Group

The node reads location.coordinates, tests the point against the stored municipality polygon and writes locationGroup.

Step 3

Debug

A Debug node shows the enriched array in the sidebar.

Show example flow as JSON (polygon shortened)
[
{"id": "tab1", "type": "tab", "label": "location-group", "disabled": false, "info": ""},
{"id": "inject1", "type": "inject", "z": "tab1", "name": "Go!", "props": [{"p": "payload"}], "repeat": "", "once": false, "payload": "", "payloadType": "date", "x": 90, "y": 120, "wires": [["fn1"]]},
{"id": "fn1", "type": "function", "z": "tab1", "name": "Input", "func": "msg.payload = [{\"id\":\"urn:ngsi-ld:1\",\"location\":{\"type\":\"Point\",\"coordinates\":[8.6,49.5]}}];\nreturn msg;", "outputs": 1, "x": 250, "y": 120, "wires": [["lg1"]]},
{"id": "lg1", "type": "location-group", "z": "tab1", "name": "", "groupingMode": "enrich", "enrichOnFilter": false, "invertFilter": false,
"locationConfig": "{\"type\":\"Point\",\"posType\":\"array\",\"latField\":\"\",\"lonField\":\"\",\"arrayField\":\"location.coordinates\",\"polyField\":\"\",\"order\":\"lonlat\"}",
"sampleJson": "[{\"id\":\"urn:ngsi-ld:1\",\"location\":{\"type\":\"Point\",\"coordinates\":[8.6,49.5]}}]",
"outputProperty": "locationGroup",
"regions": [
{"name": "Exampletown, Example County, Baden-Württemberg, 68542, Germany", "group": "Exampletown",
"polygon": {"type": "Polygon", "coordinates": [[[8.57, 49.49], [8.63, 49.49], [8.63, 49.52], [8.57, 49.52], [8.57, 49.49]]]}}
],
"x": 460, "y": 120, "wires": [["dbg1"]]},
{"id": "dbg1", "type": "debug", "z": "tab1", "name": "Output", "active": true, "tosidebar": true, "complete": "payload", "targetType": "msg", "x": 690, "y": 120, "wires": []}
]

Status and errors​

The node shows no status indicator. Notices appear as warnings in the log and the debug sidebar.

IndicatorMeaning
Warning "location-group matches points against regions. The configured Geo Type is not supported for Point-in-Polygon."A non-point geometry is configured as Geo Type. The entry receives unknown or is filtered out.
Warning "Error evaluating polygon for region '…': …"A stored polygon could not be evaluated, for example because of invalid geometry. The remaining areas are still checked.
Console warning "Location Group Node: Missing @turf/boolean-point-in-polygon dependency."The dependency is missing from the installation; there will be no matches.
Editor hint "Search failed. Proxy or API error." or "Search failed. Are you offline or is the proxy down?"The Nominatim search through the Node-RED backend failed.

Notes​

  • Nominatim only in the editor: Area search and map clicks query the public instance nominatim.openstreetmap.org through the Node-RED backend, with the user agent Node-RED-Location-Group-Node. One map click triggers three requests. Respect the usage policy of the public instance (at most one request per second) and avoid rapid click sequences.
  • External resources in the editor: The map loads Leaflet from unpkg.com and tiles from tile.openstreetmap.org. In networks without internet access the map preview stays empty and polygons cannot be searched. The deployed node's runtime behaviour is not affected.
  • Proxy: No proxy setting is provided for the backend requests to Nominatim.
  • Flow size: Polygons are stored completely in the flow. Municipality or district boundaries from OpenStreetMap quickly amount to several hundred kilobytes.
  • Order of areas: If areas overlap, the first one in the list wins.
  • Personal data: Location data of individual persons or vehicles is personal data. The node itself stores no messages, sends nothing to third parties at runtime and only writes the group name. Still check whether assigning data to an area is permitted for the respective purpose. Search terms and click positions entered in the editor are transmitted to OpenStreetMap.
  • Units: Coordinates in decimal degrees (WGS 84); GeoJSON order [longitude, latitude].

References​