openSenseMap
The node fetches master data and the latest readings of all sensors for a list of selected senseBoxes from the openSenseMap API. You pick the boxes in the edit dialog either on a map with a bounding box or via a manual list of box IDs.
- Node type
- opensensemap
- Package
- @htag/node-red-contrib-hypertegrity-environment
- Inputs / outputs
- 1 / 1
- Data source
- openSenseMap API (api.opensensemap.org)
When to use this node
openSenseMap is an open platform for environmental sensors on which schools, associations and private individuals publish their senseBoxes. The openSenseMap node brings the latest readings of selected boxes into a Node-RED flow without you having to call the API yourself. Each box is emitted as one object containing all of its sensors.
Typical use cases are:
- Local environmental data such as temperature, humidity or particulate matter from a city district fed into an urban data platform.
- Complementing citizen sensing where official monitoring stations are too far away.
- Feeding dashboards that show the state of several senseBoxes in a neighbourhood.
How the node works
Trigger
Any incoming message starts the fetch. The node never polls the API on its own.
Fetch boxes
The API is called once per configured box ID. Boxes that cannot be reached are skipped with a warning.
Transform
Each box is turned into an object with location, master data, a sensor list and a readings index keyed by sensor type.
Emit
All boxes leave the node in a single message as an array in msg.payload.
Result: An array of box objects with the latest readings of all sensors, plus counters for boxes and sensors.
The node is trigger-based. Combine it with an Inject node that fires at a fixed interval. At runtime the node only fetches the box IDs stored in the dialog. The bounding box exists solely to find and select boxes on the map in the edit dialog. Without selected boxes the node returns an empty array.
Configuration
Depending on the selection mode the edit dialog shows either the map picker or a text area for box IDs. The fields API URL and Debug Mode are visible in both modes.
| Field | Type | Default | Meaning |
|---|---|---|---|
| Name | Text | empty | Display name of the node in the flow. Without a name the node shows "openSenseMap: BBox" or "openSenseMap: n Boxes". |
| Selection Mode | Select (bbox, ids) | bbox | Bounding Box (Area on Map) shows a map with search; Manual Box IDs shows a text area. Either way a list of box IDs is stored. |
| Manual ID(s) | Text (bounding box mode only) | empty | Comma-separated box IDs. The field mirrors the current selection and can be edited directly. |
| City or address / Find | Text and button | empty | Geocodes the search term via the OpenStreetMap Nominatim service and places the bounding box around the found point. |
| Size | Slider 200 m to 20,000 m, step 200 m | 1000 (1.0 km) | Edge length of the bounding box in metres. Stored as bboxSize. |
| North (Lat), East (Lon), South (Lat), West (Lon) | Number | 52.005, 7.505, 51.995, 7.495 | Corner coordinates of the bounding box in decimal degrees. Stored as the object bbox. Changing a value reloads the box list. |
| Filter boxes | Text | empty | Filters the list of found boxes by name or ID. |
| Select Visible / Clear All | Buttons | – | Selects all boxes currently listed, or clears the selection. |
| Box IDs | Multi-line text (Manual Box IDs mode only) | empty | One senseBox ID per line. Stored as the array boxIds. |
| API URL | Text | see below | Base URL of the boxes endpoint. The node appends /<box id>. |
| Debug Mode | Checkbox | off | Writes detailed logs as warnings to the debug sidebar. |
Default values of the URL fields:
API URL: https://api.opensensemap.org/boxes
The map shows boxes that lie inside the bounding box at editing time. Only the ticked box IDs are stored. Boxes that appear in the area later are not picked up automatically.
Input
The input only acts as a trigger. The node does not evaluate any property of the incoming message.
| Property | Type | Meaning |
|---|---|---|
msg | any | Every message starts a fetch of all configured boxes. Content and properties of the message are not carried over. |
Output
The node sends one message per fetch. msg.payload is an array with one object per successfully fetched box. Counters and the raw API data are added to the message.
{
"payload": [
{
"id": "5f1a2b3c4d5e6f7a8b9c0d1e",
"name": "senseBox Example Town Hall",
"location": {"type": "Point", "coordinates": [7.5001, 52.0002]},
"exposure": "outdoor",
"model": "homeV2Wifi",
"createdAt": "2024-03-01T10:00:00.000Z",
"updatedAt": "2026-10-01T08:10:00.000Z",
"lastMeasurementAt": "2026-10-01T08:10:00.000Z",
"grouptag": ["Example Town"],
"sensors": {
"Temperature": {"id": "5f1a2b3c4d5e6f7a8b9c0d1f", "title": "Temperature", "sensorType": "HDC1080", "unit": "°C", "icon": "osem-thermometer", "value": "18.5", "timestamp": "2026-10-01T08:10:00.000Z"},
"PM10": {"id": "5f1a2b3c4d5e6f7a8b9c0d20", "title": "PM10", "sensorType": "SDS 011", "unit": "µg/m³", "icon": "osem-cloud", "value": "12.3", "timestamp": "2026-10-01T08:10:00.000Z"}
},
"measurements": {
"HDC1080": {"value": "18.5", "unit": "°C", "timestamp": "2026-10-01T08:10:00.000Z"},
"SDS 011": {"value": "12.3", "unit": "µg/m³", "timestamp": "2026-10-01T08:10:00.000Z"}
}
}
],
"boxCount": 1,
"sensorCount": 2,
"_rawBoxes": ["… unmodified API responses …"]
}
| Field | Meaning |
|---|---|
payload[].id | ID of the senseBox (API field _id). |
payload[].name | Name of the box as given by its operator. |
payload[].location | GeoJSON point in the order longitude, latitude. If the location is missing both values are null. |
payload[].exposure | Placement according to the API, for example outdoor, indoor or mobile; otherwise unknown. |
payload[].model | Hardware model of the box; otherwise unknown. |
payload[].createdAt, updatedAt, lastMeasurementAt | Timestamps from the box master data. |
payload[].grouptag | Group tags of the box as an array; empty if none are set. |
payload[].sensors | Object keyed by sensor title. Each entry holds id, title, sensorType, unit, icon plus value and timestamp of the latest reading. Without a reading, value and timestamp are null. |
payload[].measurements | Short index of the latest readings keyed by sensorType (falling back to the title). Holds value, unit and timestamp. |
boxCount | Number of boxes fetched successfully. |
sensorCount | Total number of sensors across all boxes. |
_rawBoxes | Unmodified API responses of the boxes for reference. |
Readings are passed on exactly as delivered by the API, usually as strings. If no boxes are configured or none could be reached, the node sends payload: [] with boxCount: 0 and sensorCount: 0 and without _rawBoxes.
Example flow
The package ships with an example flow. Import it in Node-RED via Menu → Import → Examples → @htag/node-red-contrib-hypertegrity-environment → opensensemap. Alternatively download opensensemap.json and import it via Menu → Import.
Inject
An Inject node named 'Go!' triggers the fetch manually.
openSenseMap
The node is preconfigured in bounding box mode without selected boxes. Select boxes in the dialog before deploying.
Debug
A Debug node 'Sensor Outputs' shows the array of box objects in the sidebar.
Show example flow as JSON
[
{"id": "tab1", "type": "tab", "label": "OpenSensemap", "disabled": false, "info": ""},
{"id": "inject1", "type": "inject", "z": "tab1", "name": "Go!", "props": [{"p": "payload"}, {"p": "topic", "vt": "str"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 100, "y": 100, "wires": [["osm1"]]},
{"id": "osm1", "type": "opensensemap", "z": "tab1", "name": "", "selectionMode": "bbox", "boxIds": [], "bbox": {"north": 52.005, "east": 7.505, "south": 51.995, "west": 7.495}, "bboxSize": 1000, "apiUrl": "https://api.opensensemap.org/boxes", "debug": false, "x": 400, "y": 100, "wires": [["debug1"]]},
{"id": "debug1", "type": "debug", "z": "tab1", "name": "Sensor Outputs", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 720, "y": 100, "wires": []}
]
Status and errors
| Indicator | Meaning |
|---|---|
| Grey ring "no boxes selected" | No box IDs are configured at startup. |
| Grey dot "n boxes ready" | n box IDs are configured at startup; the node waits for a trigger. |
| Blue dot "fetching..." | A fetch is in progress. |
| Yellow ring "no boxes selected" | A fetch was triggered but no boxes are configured or none could be reached. An empty array is sent. |
| Green dot "n boxes (m sensors)" | The fetch succeeded; n boxes with m sensors in total were emitted. |
| Red ring "API Error" | An unexpected error while assembling the requests. The message "API Error: …" is reported via node.error. |
| Red ring "error" | The fetch failed. The message "Failed to fetch data: …" is reported via node.error. |
| Warning "Failed to fetch box …" | A single box could not be loaded (timeout after 10 seconds or error response). Fetching the remaining boxes continues. |
Errors are reported via node.error and can be handled with a Catch node.
Notes
- No API key required: The openSenseMap API can be read without registration. Observe the operator's terms of use and choose a moderate polling interval, as every box is requested individually.
- External services in the editor: The address search in the edit dialog sends the search term directly from the browser to the OpenStreetMap Nominatim service. The Leaflet map library is loaded from unpkg.com. Both calls happen only while editing, not at runtime.
- Admin endpoint: To load the box list the dialog uses the endpoint
/opensensemap/boxesof the Node-RED admin API, which forwards the request server-side to the openSenseMap API (timeout 30 seconds). - Access by title or type: The
sensorsobject is keyed by sensor title and contains all sensors of a box. Themeasurementsobject offers quick access to the latest readings by sensor type. - Personal data: Many senseBoxes are operated by private individuals. Box names, group tags and locations may allow conclusions about persons. Check whether these details may be published before forwarding them to a context broker.
- Units: Units come from the sensor definitions of the respective box (for example °C, %, hPa, µg/m³) and are passed on unchanged.
- Output format: The node delivers a flat box object, not an NGSI-LD entity. Use the NGSI-LD Builder to shape the data for a context broker.