Use Case: Urban Air Quality Monitoring -> OGC SensorThings API
Status: fully modelled - all artifacts ship with the repository as
reference artifacts under schemas/usecases/luftqualitaet-sta/. They can
be imported through the ModelForge facade of a host application.
Scenario
Urban air-quality monitoring stations continuously record:
- Pollutant concentrations (NO2, PM2.5, CO)
- Accompanying meteorological data (temperature, humidity)
- GPS position
The raw data arrives via MQTT. In parallel, station master data (name, operator, calibration factors) resides in a PostgreSQL database.
The goal is to expose the measurement data as an OGC SensorThings API (FROST), so that STA-compatible clients can retrieve the data.
TAF10 is intentionally not part of this use case. TAF10 is modelled separately as low-voltage grid telemetry in Use Case: TAF10 Low-Voltage Grid Protection.
Data flow
Readings where any pollutant's quality is "bad" (the filter checks
no2.quality, pm25.quality and co.quality individually) are discarded;
"suspect" readings are flagged and forwarded. The enrich step joins station
master data from PostgreSQL by stationId and applies calibration factors. The
fan-out runs one mapping per pollutant, each posting to the FROST
/Observations endpoint.
In parallel (master-data sync, one-off / occasional): PostgreSQL master data is
mapped to STAThing and STADatastream documents and posted to
/FROST-Server/v1.1/Things and /Datastreams.
Data structures
| Element | URN |
|---|---|
| GeoPoint | urn:core:platform:civitas:element:common:GeoPoint:3ak90vqrog:1.0.0 |
| Measurement | urn:core:platform:civitas:element:luftqualitaet:Measurement:k9ta3hkxjf:1.0.0 |
| AirQualityRawReading | urn:core:platform:civitas:element:luftqualitaet:AirQualityRawReading:42iv9tjv0c:1.0.0 |
| StationCalibration | urn:core:platform:civitas:element:luftqualitaet:StationCalibration:aqokf4f3v2:1.0.0 |
| StationMasterData | urn:core:platform:civitas:element:luftqualitaet:StationMasterData:ro0sfbbjfm:1.0.0 |
| STALocation | urn:core:platform:civitas:element:sta:STALocation:vktgfkub6y:1.0.0 |
| STAThing | urn:core:platform:civitas:element:sta:STAThing:1f0bfaterl:1.0.0 |
| STAObservation | urn:core:platform:civitas:element:sta:STAObservation:np3hnkoj04:1.0.0 |
Reference relationships (all via $ref, tracked in the dependency graph):
AirQualityRawReading->Measurement->GeoPointStationMasterData->GeoPoint,StationCalibrationSTAThing->STALocation;STAObservationreferences its FROST Datastream by@iot.id
Mappings
| Mapping | URN |
|---|---|
| StationMasterData -> STAThing | urn:core:platform:civitas:mapping:luftqualitaet:station-to-sta-thing:n34qmfpf7r:1.0.0 |
| Air Quality NO2 -> STAObservation | urn:core:platform:civitas:mapping:luftqualitaet:airquality-no2-to-observation:ca39n9nqqd:1.0.0 |
| Air Quality PM2.5 -> STAObservation | urn:core:platform:civitas:mapping:luftqualitaet:airquality-pm25-to-observation:wkk3xd31h0:1.0.0 |
| Air Quality CO -> STAObservation | urn:core:platform:civitas:mapping:luftqualitaet:airquality-co-to-observation:mgth0uv301:1.0.0 |
The station mapping copies stationName, stationType and metadata into the
STAThing format. The per-pollutant mappings copy $.timestamp to
phenomenonTime/resultTime, the pollutant value to result, and the quality
flag to resultQuality.
Pipeline
urn:core:platform:civitas:pipeline:luftqualitaet:Luftqualitaet-Import:v7v1oagoqd:1.0.0
| Node | Kind | Configuration |
|---|---|---|
| ConsumeMQTT | source | Topic luftqualitaet/readings/+, Element AirQualityRawReading |
| RouteOnContent | filter | Forward when no2.quality, pm25.quality and co.quality are all != "bad" |
| LookupRecord | enrich | Key $.stationId -> PostgreSQL station database |
| Transform NO2 / PM2.5 / CO | mapping | One mapping node per pollutant |
| InvokeHTTP | sink | FROST POST /Observations |
FROST server endpoints
| Endpoint | Description |
|---|---|
GET /FROST-Server/v1.1/Things | All stations |
GET /FROST-Server/v1.1/Datastreams | All data streams |
GET /FROST-Server/v1.1/Observations | All measurements |
GET /FROST-Server/v1.1/ObservedProperties | NO2, PM2.5, CO |
GET /FROST-Server/v1.1/Things(1)/Datastreams | Datastreams of one station |
GET /FROST-Server/v1.1/Datastreams(1)/Observations?$top=10&$orderby=phenomenonTime desc | Latest 10 measurements |
Analogous scenarios ship in schemas/usecases/taf10-grid-sta/ and
schemas/usecases/smartmeter-sta/.