feat(thing): expose observedArea on Thing for STAC and DCAT-AP spatial extent#124
feat(thing): expose observedArea on Thing for STAC and DCAT-AP spatial extent#124Vishmayraj wants to merge 1 commit into
Conversation
|
Hi @Vishmayraj I think this should go into a separate branch/PR, since it looks like a distinct feature ( |
Thanks for the feedback. Just to clarify - these are already separate PRs on independent branches ( |
What this does
Adds
observedAreaas a computed derived field on theThingentity, returning the aggregated spatial footprint of each Thing in a singleGET /Thingsresponse.{ "@iot.id": 1, "name": "thing_name_1", "observedArea": { "type": "Polygon", "coordinates": [[[97.72, 25.12], [-165.38, 37.54], "..."]] } }Spec note
observedAreais defined by OGC STA 1.1 onDatastream, not onThing. Noticing the already made extensions from the standard entity Thing by addingCommit, this PR addsobservedAreaas a deliberate extension at the Thing level, consistent with istSOS4's existing pattern.Why this matters
In the STA to DCAT-AP 3.0 mapping,
Thingis best modelled as adcat:DatasetSeriesa device-level grouping container for all its Datastreams. Connectors and harvesters that build a device-level catalog index need the spatial footprint of each Thing without having to expand into its Datastreams.Without this field, that requires N requests:
With this field, a single
GET /Thingsgives the full device index including spatial extent in one call. This is paired with thephenomenonTimePR which does the same for temporal extent, together enabling completedcat:DatasetSeriesmetadata from single request.How it works
The PostgreSQL function
observedArea(sensorthings."Thing")already existed in the schema. It computesST_ConvexHull(ST_Collect(...))across all Datastreams belonging to the Thing, returningNULLif no Datastreams have geometry yet. This PR wires it up to the API layer with minimal changes:models/thing.py-> declaresobserved_area = Column("observedArea", Geometry)on the Thing ORM model so SQLAlchemy can select itsta2rest.py-> addsobserved_areato Thing'sDEFAULT_SELECTso it appears in all Thing responses without needing$selectThe existing
get_select_attrinvisitors.pyalready handlesGeometrycolumns by wrapping them inST_AsGeoJSON, so the output is clean GeoJSON with no additional changes needed.Testing