Draft

OGC Standard

OGC SensorThings API 2.0
Hylke van der Schaaf Editor Steve Liang Editor
Version: 0.1
Additional Formats: XML PDF DOC
OGC Standard

Draft

Document number:23-019
Document type:OGC Standard
Document subtype:Implementation
Document stage:Draft
Document language:English

License Agreement

Use of this document is subject to the license agreement at https://www.ogc.org/license

Suggested additions, changes and comments on this document are welcome and encouraged. Such suggestions may be submitted using the online change request form on OGC web site: http://ogc.standardstracker.org/




I.  Abstract

<Insert Abstract Text here>

II.  Keywords

The following are keywords to be used by search engines and document catalogues.

ogcdoc, OGC document, API, OData, openapi, html, MQTT


III.  Preface

NOTE:  Insert Preface Text here. Give OGC specific commentary: describe the technical content, reason for document, history of the document and precursors, and plans for future work.

There are two ways to specify the Preface: “simple clause” or “full clasuse”

If the Preface does not contain subclauses, it is considered a simple preface clause. This one is entered as text after the .Preface label and must be placed between the AsciiDoc document attributes and the first AsciiDoc section title. It should not be give a section title of its own.

If the Preface contains subclauses, it needs to be encoded as a full preface clause. This one is recognized as a full Metanorma AsciiDoc section with te title “Preface”, i.e. == Preface. (Simple preface content can also be encoded like full preface.)

Attention is drawn to the possibility that some of the elements of this document may be the subject of patent rights. The Open Geospatial Consortium shall not be held responsible for identifying any or all such patent rights.

Recipients of this document are requested to submit, with their comments, notification of any relevant patent claims or other intellectual property rights of which they may be aware that might be infringed by any implementation of the standard set forth in this document, and to provide supporting documentation.

IV.  Security Considerations

bla bla

V.  Submitting Organizations

The following organizations submitted this Document to the Open Geospatial Consortium (OGC):

  • Fraunhofer-Gesellschaft, Germany
  • University of Calgary, Canada
  • SensorUp Inc., Canada
  • Keys, USA
  • DataCove e.U., Austria
  • Secure Dimensions, Germany
  • CREAF, Spain

1.  Scope

The OGC SensorThings API Version 2 provides an open Standard-based and geospatial-enabled framework to interconnect the Internet of Things devices, data, and applications over the web. It defines a data model, an abstract REST API for interacting with the data model, and HTTP and MQTT protocol bindings for the REST API. Furthermore, it provides support for push notifications for data changes over MQTT.

The data model, and API can be extended, and additional protocol bindings or data encodings, can be added by future extensions of the standard.

2.  Conformance

This standard defines XXXX.

Requirements for N standardization target types are considered:

  • AAAA

  • BBBB

Conformance with this standard shall be checked using all the relevant tests specified in Annex A (normative) of this document. The framework, concepts, and methodology for testing, and the criteria to be achieved to claim conformance are specified in the OGC Compliance Testing Policies and Procedures and the OGC Compliance Testing web site.

In order to conform to this OGC® interface standard, a software implementation shall choose to implement:

  • Any one of the conformance levels specified in Annex A (normative).

  • Any one of the Distributed Computing Platform profiles specified in Annexes TBD through TBD (normative).

All requirements-classes and conformance-classes described in this document are owned by the standard(s) identified.

3.  Normative references

The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.

Steve Liang, Tania Khalafbeigi, Hylke van der Schaaf: OGC 18-088, OGC SensorThings API Part 1: Sensing Version 1.1. Open Geospatial Consortium (2021). http://www.opengis.net/doc/is/sensorthings/1.1.0.

Katharina Schleidt, Ilkka Rinne: OGC 20-082r4, Topic 20 — Observations, measurements and samples. Open Geospatial Consortium (2023). http://www.opengis.net/doc/as/om/3.0.

ISO: ISO 19156:2023, Geographic information — Observations, measurements and samples. International Organization for Standardization, Geneva (2023). https://www.iso.org/standard/82463.html.

Alexandre Robin: OGC 08-094r1, OGC® SWE Common Data Model Encoding Standard. Open Geospatial Consortium (2011). https://portal.ogc.org/files/?artifact_id=41157.

Alex Robin: OGC 17-011r2, JSON Encoding Rules SWE Common / SensorML. Open Geospatial Consortium (2018). http://www.opengis.net/doc/BP/SWE-JSON/1.0.

[NO INFORMATION AVAILABLE]

P. Bryan, M. Nottingham (eds.): IETF RFC 6902, JavaScript Object Notation (JSON) Patch. RFC Publisher (2013). https://www.rfc-editor.org/info/rfc6902.

J. Snell: IETF RFC 7240, Prefer Header for HTTP. RFC Publisher (2014). https://www.rfc-editor.org/info/rfc7240.

E. Rescorla: IETF RFC 2818, HTTP Over TLS. RFC Publisher (2000). https://www.rfc-editor.org/info/rfc2818.

Handl R, Pizzo M (Chair): OASIS OData-Part1, OData Version 4.01. Part 1: Protocol. OASIS (2020). http://docs.oasis-open.org/odata/odata/v4.01/os/part1-protocol/odata-v4.01-os-part1-protocol.html.

Handl R, Pizzo M (Chair): OASIS OData-Part2, OData Version 4.01. Part 2: URL Conventions. OASIS (2020). http://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html.

Handl R, Pizzo M (Chair): OASIS OData-CSDL-JSON-v4.01, OData Common Schema Definition Language (CSDL) JSON Representation Version 4.01. OASIS (2020). http://docs.oasis-open.org/odata/odata-csdl-json/v4.01/os/odata-csdl-json-v4.01-os.html.

Coppen R, Banks A, Briggs E, Borgendale K, Gupta R (Chair): OASIS mqtt-v5.0, MQTT Version 5.0. OASIS (2019). http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html.

Arliss Whiteside, Jim Greenwood: OGC 06-121r9, OGC Web Service Common Implementation Specification. Open Geospatial Consortium (2010). https://portal.ogc.org/files/?artifact_id=38867.

EDITORIAL NOTE

Check which of these are normative and which should go to the bibliography at the end.

4.  Terms and definitions

This document uses the terms defined in OGC Policy Directive 49, which is based on the ISO/IEC Directives, Part 2, Rules for the structure and drafting of International Standards. In particular, the word “shall” (not “must”) is the verb form used to indicate a requirement to be strictly followed to conform to this document and OGC documents do not use the equivalent phrases in the ISO/IEC Directives, Part 2.

This document also uses terms defined in the OGC Standard for Modular specifications (OGC 08-131r3), also known as the ‘ModSpec’. The definitions of terms such as standard, specification, requirement, and conformance test are provided in the ModSpec.

For the purposes of this document, the following additional terms and definitions apply.

This document uses the terms defined in Sub-clause 5.3 of OGC 06-121r9, which is based on the ISO/IEC Directives, Part 2, Rules for the structure and drafting of International Standards. In particular, the word “shall” (not “must”) is the verb form used to indicate a requirement to be strictly followed to conform to this standard.

For the purposes of this document, the following additional terms and definitions apply.

term used for exemplary purposes

Note 1 to entry: An example note.

Example

Here’s an example of an example term.

[SOURCE: ]

5.  Conventions

5.1.  Introduction

This sections provides details and examples for any conventions used in the document. Examples of conventions are symbols, abbreviations, use of XML schema, or special notes regarding how to read the document.

5.2.  Identifiers

The normative provisions in this standard are denoted by the URI

http://www.opengis.net/spec/sensorthings/2.0

All requirements and conformance tests that appear in this document are denoted by partial URIs which are relative to this base.

6.  SensorThings API overview

6.1.  Who should use the OGC SensorThings API

Organizations that need web-based platforms to manage, store, share, and analyze real-time sensor observation data should use the OGC SensorThings API. The OGC SensorThings API simplifies and accelerates the development of modern location enabled digital monitoring and control applications. Application developers can use this open standard to connect to various sensor devices and create innovative applications without worrying about the daunting heterogeneous protocols of the disparate vendor hardware including gateways and services. Sensor device manufacturers can also use OGC SensorThings API as the API can be embedded within various hardware and software platforms, thus allowing the various sensing devices to effortlessly connect with the OGC Standard-compliant servers around the world.

While the OGC SensorThings API was initially designed with IoT applications in mind, it has proven valuable for many non-IoT use cases as well:

  • Environmental Monitoring: Managing data from fixed monitoring stations for air quality, water quality, weather, and climate observations that may not be considered traditional IoT devices

  • Scientific Research: Handling laboratory measurements, experimental data, and field observations where standardized data management and interoperability are crucial

  • Urban Planning, Smart Cities & Digital Twins: Urban planners & municipal corporations can use the API to monitor various environmental and infrastructure metrics, like noise levels, pollution, or green space usage, helping with sustainable city planning. Large buildings or campuses can have digital twins that track HVAC systems, lighting, occupancy, occupancy status and safety conditions. SensorThings API allows for efficient, standardized data collection from these disparate systems.

  • Historical Data Archives: Providing standardized access to historical observation datasets

  • Citizen Science: Supporting data collection and management from volunteer observers and manual measurements

  • Regulatory Compliance: Managing environmental compliance for monitoring data from both automated and manual sampling programs

In summary, the OGC SensorThings API is transforming the numerous disjointed networked sensor systems into a fully connected platform where complex tasks can be synchronized and performed. The flexible data model and powerful query capabilities make SensorThings API suitable for any application involving time-series observations, regardless of whether networked sensor devices are involved.

6.2.  Benefits of the OGC SensorThings API

In today’s world, most IoT devices (e.g., sensors and actuators) have proprietary software interfaces defined by their manufacturers and used selectively. New APIs are often required and developed on an as-needed basis, often in an environment with resource limitations and associated risks. This situation requires significant investment on the part of developers for each new sensor or project involving multiple systems and on the part of the providers of sensors, gateways, and portals or services where observations and measurements are required.

As a standardized data model and interface for sensors in the WoT and IoT, the OGC SensorThings API offers the following key benefits:

  1. Interoperability and Integration

    • Enables seamless integration between different sensor systems, platforms, and applications

    • Reduces vendor lock-in by providing a standardized interface

    • Facilitates data exchange across organizational boundaries and domains

  2. Cost and Time Efficiency

    • Lowers development costs through standardized implementation patterns

    • Reduces time-to-market for IoT solutions

    • Minimizes the need for custom interface development

    • Simplifies maintenance and updates across the system

  3. Scalability and Flexibility

    • Supports both small-scale deployments and large enterprise solutions

    • Adapts to various use cases from environmental monitoring to smart cities

    • Enables easy addition of new sensors and data sources

    • Supports both real-time and historical data management

  4. Data Quality and Governance

    • Provides consistent metadata management

    • Ensures data provenance through standardized observation tracking

    • Supports regulatory compliance through structured data handling

    • Enables better data discovery and reuse

  5. Modern Web-GIS Support

    • Aligns with REST architectural principles

    • Supports cloud-native deployments

    • Enables edge computing scenarios

  6. Enhanced Analytics and Innovation

    • Simplifies data integration for analytics and AI/ML applications

    • Enables standardized access to historical datasets

    • Supports real-time monitoring and alerting

    • Facilitates development of innovative applications and services

These benefits make the OGC SensorThings API particularly valuable in today’s rapidly evolving digital landscape, where organizations increasingly rely on sensor data for decision-making and automation.

6.3.  SensorThings API Overview

EDITORIAL NOTE

Go over these parts

The OGC SensorThings API data model consists of three main parts:

  1. the Sensing part,

  2. the Sampling part and

  3. the Tasking part.

Additionally, SensorThings API supports the following two extensions to the data model:

  1. the Sensing Extension (Observations & Measurements) and

  2. the Relations extension

The core data model allows sensor devices and applications to CREATE, READ, UPDATE, and DELETE (i.e., HTTP POST, GET, PATCH, and DELETE) data and metadata in a SensorThings service. The Sensing part is designed based on the OGC/ISO Observation, Measurements and Samples (OMS) model ( OGC 20-082r4 and ISO 19156:2023).

An Observation is modeled as an act that produces a result whose value is an estimate of a property of a given Feature.

An Observation instance is characterized by its event time (e.g., resultTime and phenonmenonTime), Feature, ObservedProperty, and the procedure used (often a Sensor).

Moreover, Things are also modeled in the SensorThings API. A Thing draws from the same concept as a Host in OMS where a Host is defined as a collection of Observers (defined as Sensor in SensorThings API). Formally, its definition follows the ITU-T definition: “ an object of the physical world (physical things) or the information world (virtual things) that is capable of being identified and integrated into communication networks[1].

The geographical Locations of Things are useful in almost every application and as a result are included as well. For the Things whose location changed, the HistoricalLocations entities offer the history of the Thing’s locations.

A Thing also can have multiple Datastreams. A Datastream is a collection of Observations grouped by the same ObservedProperty, Sensor and optionally by Feature and ObservingProcedure.

An Observation is an event performed by a Sensor that produces a result whose value is an estimate of an ObservedProperty of any given Feature which may be a proximate or ultimate FeatureofInterest. Details of each above described entity are provided in Clause 7.

6.4.  SensorThings API and Relation to ISO/OGC Observations, Measurements and Samples

Managing and retrieving observations and metadata from IoT sensor systems is one of the most common use cases. As a result, SensorThings API’s sensing part is designed based on the OMS model. OMS defines models for the exchange of information describing observation acts, their results as well as the feature involved in sampling when making observations.

SensorThings API defines nine entities for the IoT sensing applications and several additional entities in various extensions. Table 1 lists each component and its relationship with OMS. SensorThings API uses the term of Sensor to describe the Observer that is used in generating an Observation, instead of using OMS’ term of Observer.

Table 1 — SensorThings API Sensing entities and equivalent concepts in the Observations, Measurements and Samples standard

SensorThings API EntitiesOMS Concepts

Thing

Host

Datastream

ObservationCollection, ObservingCapability

Sensor

Observer

Observation

Observation

ObservedProperty

Observed Property

Feature

Feature

Deployment (OM Extension)

Deployment

ObservingProcedure (OM Extension)

Observing Procedure

Sample (Sampling Extension)

Sample

Sampling (Sampling Extension)

Sampling

SamplingProcedure (Sampling Extension)

Sampling Procedure

PreparationProcedure (Sampling Extension)

Preparation Procedure

PreparationStep (Sampling Extension)

Preparation Step

6.5.  SensorThings API 2.0 changes from 1.1

From the SensorThings API version 1.1 (OGC 18-088) to 2.0 changes have been made to both the data model and the API. The changes to the data model have been summarised in Table 2 and Figure 1.

Table 2 — Changes in the SensorThings API 2.0 data model compared to v1.1

EntityChanges
All
  • @iot.id is renamed to id

  • @iot.selfLink is renamed to @id, to match OData 4.01

  • All @iot.navigationLink are renamed to @navigationLink, to match OData 4.01

  • @iot.nextLink is renamed to @nextLink to match OData 4.01

Sensor
  • description attribute is now optional and not mandatory

  • definition attribute added

Thing
  • description attribute is now optional and not mandatory

  • definition attribute added

Location
  • description attribute is now optional and not mandatory

  • For a Thing having multiple Locations, these Locations MAY be in same encodingTypes OR the encodingTypes MAY be in different spaces (e.g., one encodingType in Geometrical space and one encodingType in Topological space).

  • definition attribute added

Datastream
  • description attribute is now optional and not mandatory

  • resultType replaces the observationType attribute, this eliminates MultiDatastream entity

  • unitOfMeasurement SHALL be embedded within the observedType attribute and does not exist as an independent attribute within the Datastream entity

  • A Datastream can link to multiple ObservedProperties which was only possible with MultiDatastream entity earlier. The SWE-Common based resultType attribute eliminates the need for having a separate MultiDatastream entity

  • A Datastream can now be linked to the Feature it observes as an optional link, named UltimateFeatureOfInterest, between Datastream and Feature is introduced

  • definition attribute added

ObservedProperty

description attribute is now optional and not mandatory

Observation
  • properties replaces the parameters attribute.

  • An Observation may or may not link to any Feature in contrast to the mandatory link between Observation and FeatureOfInterest from v1.x.

  • resultTime is now optional and can be left out completely, instead of defaulting to a null value.

Feature
  • The Feature entity replaces the FeatureOfInterest entity from 1.x as it now takes the role of UltimateFeatureOfInterest or ProximateFeatureOfInterest depending upon the context and links with Observation and Datastream entities

  • definition attribute added

FeatureType

The FeatureType entity is added, and makes it easier to handle type information for Features

 

Sensing Core Changes

Figure 1 — Sensing Core Changes

6.6.  Relation to OASIS-OData

OData is an API standard for exchanging relational data. It allows for the definition of a consistent REST API on any relational data model. OData specifies how clients can inspect the data model and how they can perform Create, Read, Update and Delete actions. OData comes with a very powerful query language that allows users to compose the response to queries such that only a minimal number of queries is required to fetch needed data, regardless of the use case of the client. The OData specification also defines filtering mechanisms that allows filtering across relations. OData uses JSON-encoding by default, and specifies generic rules for encoding relational data models in JSON.

The OGC SensorThings API v2 interface is not an OData interface and does not claim to be an OData service. It specifies a subset of the OData 4.01 specification, and extends it at the same time with certain features optimized for accessing sensor data. A SensorThings API Server implementation can implement the full OData specification. An OData client can access a SensorThings API service.

EDITORIAL NOTE

Check if this is true

7.  The SensorThings API Core Data Model

7.1.  Introduction

All data model requirements are grouped in the following requirements class:

The OGC SensorThings API v2.0 Core data model is depicted in Figure 2

 

Sensing Core

Figure 2 — UML class diagram of the SensorThings API Core data model

In this section, we define each entity depicted in Figure 2 and its relationships with other entities. Additionally, we also provide examples to model the entities in different contexts.

7.2.  Recurring attributes

Several attributes are used in several classes. They always have the same semantic meaning, regarless of the class they are used in.

id

The primary key of the class. An Entity is uniquely identified, among Entities of the same class and in the same service, by its id value. The data type of the id attribute may vary between services, or even between classes in the same service, but must be the same for all Entities of the same class in the same service. In most cases the value of the id attribute of an Entity will be generated by the service when the Entity is created, but a service may allow users to specify a value.

name

The name of an Entity is a (short) character string that describes the Entity. It does not need to be unique among entities of the same type, though, when two entities of the same type have the same name, there should be another distinguishing attribute. Two Things with the same name are likely to cause confusion, but two Datastreams with the same name are generally acceptable, as long as these Datastreams are associated to different Things.

description

The description of an Entity is a longer, human readable, character string giving a descriptive text of the Entity.

definition

The definition of an Entity is a unique external identifier, linking the Entity to an external, autorative source. The definition allows for different services to represent different aspects of the same systems. It can, for instance, be a URL to a feature in an OGC API — Features service, or a DID pointing to a crytographically signed resource.

properties

A set of user-defined named values. The values may be of any type, including nested arrays or name-value sets. In the default JSON encoding the properties attribute is a JSON-Object.

7.3.  Thing

Requirement 1: Class Thing

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/thing
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Thing entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 3.

B

Each Thing entity SHALL have the direct relation between a Thing entity and other entity types listed in Table 4.

The SensorThings API follows the ITU-T definition, i.e., with regard to the Internet of Things, a thing is an object of the physical world (physical things) or the information world (virtual things) that is capable of being identified and integrated into communication networks [ITU-T Y.2060]. A Thing is related to the Platform entity as described in Section 4.9.2.1 of [OGC 16-079] in a way that any entity that can be modelled as a Thing MAY be subsequently translated to a Platform and vice versa.

Examples of the use of Thing are:

  • A weather station that houses a varying set of environmental sensors

  • A thermostat in a room, monitoring and controlling the temperature on that room

  • A drone that mounts a LiDAR sensor for mapping purposes

  • A science vessel that has many sensors installed

  • An upstream oil well that is equipped with compound gas detection devices

Table 3 — Attributes of a Thing entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Thing entity, commonly a descriptive name.

String

1

definition

The URI linking the Thing to an external definition. Dereferencing this URI SHOULD result in a representation of the definition of the Thing.

URI

0..1

description

This is a short description of the corresponding Thing entity.

String

0..1

properties

A JSON Object containing user-annotated properties.

JSON_Object

0..1

Table 4 — Direct relation between a Thing entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Location

The Location entity locates the Thing. Multiple Things MAY be located at the same Location. A Thing MAY not have a Location.

A Thing SHOULD have only one physical location, but this location may be described in different ways, using different representations. In such case, the Thing MAY have more than one Locations.

Location

0..*

HistoricalLocations

A Thing has zero-to-many HistoricalLocations. A HistoricalLocation has one-and-only-one Thing.

HistoricalLocation

0..*

Datastreams

A Thing MAY have zero-to-many Datastreams.

Datastream

0..*

 

{
 
"@context": "https://example.org/v2.0/$metadata#Things/$entity",
 
"@id": "Things(1)",
 
"id": 1,
 
"name": "Oven",
 
"description": "This thing is an oven.",
 
"properties": {
   
"owner": "Ulrike Schmidt",
   
"color": "Black"
 
},
 
"Locations@navigationLink": "Things(1)/Locations",
 
"Datastreams@navigationLink": "Things(1)/Datastreams",
 
"HistoricalLocations@navigationLink": "Things(1)/HistoricalLocations"
}

Listing 1 — Example of a Thing entity returned by a HTTP end point.

7.4.  Location

Requirement 2: Class Location

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/location
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Location entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 5.

B

Each Location entity SHALL have the direct relation between a Location entity and other entity types listed in Table 6.

The Location entity geo-locates the Thing or the Things it associated with. A Thing’s Location entity is defined as the last known location of the Thing.

Section 7.1.4 of [OGC 20-082r4 and ISO 19156:2023] provides a detailed explanation of observation location. Examples of the use of Location are:

  • An air quality sensing facility’s Location can be the physical location where the facility is situated, but the (proximate) Feature that is characterized by the Observation could be the air envelope around the Sensor which is subsequently used to estimate the air quality of the district where the facility is situated.

  • A drone that mounts a LiDAR Sensor may have its Location as the geo-referenced area over which the drone is scheduled to fly, whereas the Feature could be the individual objects mapped by the Sensor within that geo-referenced area

Table 5 — Attributes of a Location entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Location entity, commonly a descriptive name.

String

1

definition

The URI linking the Location to an external definition. Dereferencing this URI SHOULD result in a representation of the definition of the Location.

URI

0..1

encodingType

The encoding type of the Location property. (see Table 7 for some suggested ValueCodes)

String

1

location

The identifiable location of the Thing

ANY

1

description

The description about the Location

String

0..1

properties

A JSON Object containing user-annotated properties.

JSON_Object

0..1

Table 6 — Direct relation between a Location entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Things

The Things located at the source Location. Multiple Things MAY locate at the same Location.

Thing

0..*

HistoricalLocations

The HistoricalLocations of things that have been located at this Location.

HistoricalLocation

0..*

Table 7 — Non-exhaustive list of code values used for identifying types for the encodingType of the Location and Feature entities

encodingTypeValueCode Value
GeoJSONapplication/geo+json
GeoPoseapplication/geopose+json
WKTtext/plain

 

{
 
"@context": "https://example.org/v2.0/$metadata#Locations/$entity",
 
"@id": "Locations(1)",
 
"id": 1,
 
"name": "CCIT",
 
"description": "Calgary Center for Innvative Technologies",
 
"encodingType": "application/geo+json",
 
"location": {
   
"type": "Feature",
   
"geometry":{
     
"type": "Point",
     
"coordinates": [-114.06,51.05]
   
}
 
},
 
"Things@navigationLink": "Locations(1)/Things",
 
"HistoricalLocations@navigationLink": "Locations(1)/HistoricalLocations",
}

Listing 2 — Example of a Location entity using a GeoJSON Feature.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Locations/$entity",
 
"@id": "Locations(2)",
 
"id": 2,
 
"name": "IOSB",
 
"description": "Fraunhofer-Institut für Optronik, Systemtechnik und Bildauswertung IOSB",
 
"encodingType": "application/geo+json",
 
"location": {
   
"type": "Point",
   
"coordinates": [8.426, 49.015]
 
},
 
"Things@navigationLink": "Locations(2)/Things",
 
"HistoricalLocations@navigationLink": "Locations(2)/HistoricalLocations",
}

Listing 3 — Example of a Location entity using a GeoJSON Geometry.

NOTE:  When using a GeoJSON encoding for the location attribute, the value can either be a GeoJSON Feature or a GeoJSON Geometry.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Locations/$entity",
 
"@id": "Locations(3)",
 
"id": 3,
 
"name": "Hamburg Port",
 
"description": "Location at Hamburg Harbor",
 
"encodingType": "text/plain",
 
"location": "POINT(9.9937 53.5511)",
 
"Things@navigationLink": "Locations(3)/Things",
 
"HistoricalLocations@navigationLink": "Locations(3)/HistoricalLocations"
}

Listing 4 — Example of a Location entity using WKT.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Locations/$entity",
 
"@id": "Locations(4)",
 
"id": 4,
 
"name": "Weather Station Alpha",
 
"description": "Rooftop weather monitoring station",
 
"encodingType": "application/vnd.ogc.fg+json",
 
"location": {
   
"type": "Feature",
   
"place": {
     
"type": "Point",
     
"coordinates": [13.4050, 52.5200]
   
},
   
"geometry": {
     
"type": "Point",
     
"coordinates": [13.4050, 52.5200]
   
},
   
"properties": {
     
"floor": 5,
     
"building": "Tower A",
     
"installation_date": "2023-01-15"
   
}
 
},
 
"Things@navigationLink": "Locations(4)/Things",
 
"HistoricalLocations@navigationLink": "Locations(4)/HistoricalLocations"
}

Listing 5 — Example of a Location entity using JSON-FG.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Locations/$entity",
 
"@id": "Locations(5)",
 
"id": 5,
 
"name": "Drone Camera Position",
 
"description": "Position and orientation of aerial survey drone",
 
"encodingType": "application/geopose+json",
 
"location": {
   
"position": {
     
"lat": 48.8584,
     
"lon": 2.2945,
     
"h": 300.5
   
},
   
"quaternion": {
     
"x": 0.0,
     
"y": 0.0,
     
"z": 0.7071,
     
"w": 0.7071
   
}
 
},
 
"Things@navigationLink": "Locations(5)/Things",
 
"HistoricalLocations@navigationLink": "Locations(5)/HistoricalLocations"
}

Listing 6 — Example of a Location entity using OGC GeoPose.

7.5.  HistoricalLocation

Requirement 3: Class HistoricalLocation

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/historical-location
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each HistoricalLocation entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 8.

B

Each HistoricalLocation entity SHALL have the direct relation between a HistoricalLocation entity and other entity types listed in Table 9.

C

When the Locations relation of a Thing changes, a new HistoricalLocation SHALL be created and added to the Thing automatically by the service. The current Location(s) of the Thing SHALL only be added to this autogenerated HistoricalLocation automatically by the service, and SHALL not be created as HistoricalLocation directly by user.

D

When a user directly adds new HistoricalLocation, and the time of this new HistoricalLocation is later than the latest HistoricalLocation for the Thing, then the Locations of the Thing are changed to the Locations of this new HistoricalLocation.

A Thing’s HistoricalLocation entity set provides the times of the current (i.e., last known) and previous locations of the Thing. It can be used to model the path observed by a moving Thing. An example of the use of HistoricalLocation is:

  • A drone that measures methane leaks over a large basin may want to record the trajectory through which it flies. HistoricalLocation should then record the individual Locations of the drone over time.

The HistoricalLocation can also be created, updated and deleted. One use case is to migrate historical observation data from an existing observation data management system to a SensorThings API system. Another use case is to track the Location of a Thing, when a permanent network connection is not available. If the Location of a Thing is changed at a later time, when a network connection is available again, then the auto-generated Time of the HistoricalLocation entity would not reflect the time when the Thing was actually at the set Location, but only the time at which the change was sent to the server. To resolve this, the Location of a Thing can also be changed by adding a HistoricalLocation. If the time of a manually created HistoricalLocation is later than the time of all existing HistoricalLocations, then the Location of the Thing is updated to the Location of this manually created HistoricalLocation.

Table 8 — Attributes of a HistoricalLocation entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

time

The time when the Thing is known at the Location.

TM_Instant

1

Table 9 — Direct relation between a HistoricalLocation entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Locations

The Locations for this HistoricalLocation. One HistoricalLocation SHALL have at least one Location.

Location

1..*

Thing

The Thing this HistoricalLocation positions in time. A HistoricalLocation has exactly one Thing.

Thing

1

 

{
 
"@context": "https://example.org/v2.0/$metadata#HistoricalLocations/$entity",
 
"@id": "HistoricalLocations(1)",
 
"id": 1,
 
"time": "2020-03-20T16:35:23.383586Z",
 
"Thing@navigationLink": "HistoricalLocations(1)/Thing",
 
"Locations@navigationLink": "HistoricalLocations(1)/Locations"
}

Listing 7 — Example of a HistoricalLocation entity returned by a HTTP end point.

7.6.  Datastream

Requirement 4: Class Datastream

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/datastream
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Datastream entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 10.

B

Each Datastream entity SHALL have the direct relation between a Datastream entity and other entity types listed in Table 11.

A Datastream groups a collection of Observations into a time series measuring the same ObservedProperties by the same Sensor for the same Thing and the same FeatureOfInterest. Examples of Datastreams could be:

  • An air quality monitoring station may have multiple Datastreams, each recording a specific pollutant measured by a specific sensor.

  • A sensor that measures multiple ObservedProperties can generate a single Datastream with a composite resultType.

A Datastream can both have a Proximate- and an UltimateFeatureOfInterest. The UltimateFeatureOfInterest is the broadest domain feature that the Observations in the Datastream can be said to represent. The ProximateFeatureOfInterest is a more precise specification of a part of the Ultimate Feature. An individual Observation can also have a ProximateFeatureOfInterest, which would, in most cases, be a sample with a limited set of Observations taken on it.

For example, in water quality the Ultimate FeatureOfInterest could be a river, while the ProximateFeatureOfInterest is a section of the river, or a specific point in the river where measurements or samples are taken. If samples are taken, these samples are the ProximateFeatureOfInterest linked directly to the Observations taken on them.

Table 10 — Attributes of a Datastream entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Datastream entity, commonly a descriptive name.

String

1

definition

The URI linking the Datastream to an external definition. Dereferencing this URI SHOULD result in a representation of the definition of the Datastream.

URI

0..1

description

The description of the Datastream entity.

String

0..1

resultType

The formal description of the result field of the Observations in this Datastream. Contains the unit of measurement and the @id of the ObservedProperty.

JSON_Object (SWE-Common AbstractDataComponent)

1

resultEncoding

The default encoding of the result field of the Observations in this Datastream. The default encoding is JSONEncoding.

JSON_Object (SWE-Common Encoding)

0..1

observedArea

The spatial bounding box of the spatial extent of the Feature that belong to the Observations associated with this Datastream. This is usually generated by the server.

Geometry

0..1

phenomenonTime

The temporal interval of the phenomenon times of all observations belonging to this Datastream. This is usually generated by the server.

TM_Period

0..1

resultTime

The temporal interval of the result times of all observations belonging to this Datastream. This is usually generated by the server.

TM_Period

0..1

properties

A JSON Object containing user-annotated properties.

JSON_Object

0..1

TM_Period is by default encoded as a complex type with a start (mandatory) and end (mandatory) attributes of type TM_Instant.

Table 11 — Direct relation between a Datastream entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Thing

The Thing this Datastream holds Observations for.

Thing

1

Sensor

The Sensor that made the Observations in this Datastream.

Sensor

1

ObservedProperty

The ObservedProperty of the Observations in this Datastream. The Observations in a Datastream may hold values for multiple ObservedProperties, but the ObservedProperties are the same for all Observations in the same Datastream. The service must ensure the linked ObservedProperties match the definitions used in the resultType.

ObservedProperty

1..*

Observations

The Observations for a Datastream.

Observation

0..*

ProximateFeatureOfInterest

This relation links to a Feature that has the role ProximateFeatureOfInterest for all the Observations in a Datastream.

Feature

0..1

UltimateFeatureOfInterest

This relation links to a Feature that has the role UltimateFeatureOfInterest for all the Observations in a Datastream.

Feature

0..1

The resultType defines the result types for specialized single and multi observations based on the JSON encoding of the SWE Common Data Model (OGC 08-094r1 and OGC 17-011r2, or, once released: OGC 24-014). The result of an Observation may be a single simple number or String, or it may contain a complex JSON structure holding multiple values for multiple ObservedProperties. The exact definition for this result structure, and which unit of measurement and which ObservedProperty pertains to each value in the result structure is exactly described by this resultType Object.

The resultType contains references to the ObservedProperty or ObservedProperties of the Observations in the Datastream. When a change is made to the resultType, the server MUST ensure the ObservedProperties linked to the Datastream match the references used in the the definition attribute(s) of the resultType, and create or remove relations as needed. If the resultType contains references to non-existing ObservedProperties the request must be rejected with a Bad Request error. The values of the definition fields in the resultType must be valid entity-ids ( @id) of ObservedProperties. The structure of the resultType must not be changed once a Datastream has Observations, since the existing Observations would not fit the new structure.

EDITORIAL NOTE

Update reference to new SWE-Common: 24-014

In most cases each Observation holds a single numeric result value, measured by a single Sensor. In this case the resultType is of the SWE-Common class Quantity (though a number could also be a Count) and thus must have the fields type, definition, label, and uom.

  • The type field defines the type of the result and has the value Quantity.

  • The definition must be the same as the definition field in the single ObservedProperty linked to the Datastream.

  • The uom field contains the unit of measurement, and is an object that must contain either a code field with the UCUM code of the unit, or a href field with a URI pointing to a unit definition. It may also contain the label and symbol fields that can be displayed in user interfaces.

  • The label field is somewhat redundant in this case, but since it is mandatory it can be set to the same value as the ObservedProperty name.

 

{
 
"name": "Oven temperature",
 
"description": "This is a datastream measuring the air temperature in an oven.",
 
"resultType": {
   
"type": "Quantity",
   
"label": "Temperature",
   
"definition": "ObservedProperties(1)",
   
"uom": { "code": "Cel", "label": "degree Celsius", "symbol": "°C" }
 
}
}

Listing 8 — A Datastream example measuring a scalar Observation

 

{
 
"result": 25.1,
 
"phenomenonTime":  {
   
"start": "2021-13-14T15:16:00Z"
 
}
}

Listing 9 — An Observation for the Datastream defined in the example above

Another common type of result is a value from a key list. An example would be an Observation of the current weather as Fair or Overcast, or the geological dating of a rock sample to be Jurassic. In the latter case, the code space that defines the values could be the Sweet ontology. In this example the resultType is a Category and thus must have the fields type, definition, label, and codeSpace.

  • The type field defines the type of the result and has the value Category.

  • The definition must be the same as the definition field in the single ObservedProperty linked to the Datastream.

  • The codeSpace field must be a reference that defines the valid values that can be used as results.

  • The label field is somewhat redundant in this case, but since it is mandatory it can be set to the same value as the ObservedProperty name.

 

{
 
"name": "Sample Dating",
 
"description": "This is a datastream containing the geological datings of rock samples.",
 
"resultType": {
   
"type": "Category",
   
"label": "Period",
   
"definition": "ObservedProperties(2)",
   
"codeSpace": "http://sweetontology.net/stateTimeGeologic/"
 
}
}

Listing 10 — A Datastream example for Observations with category values from a predefined code space

 

{
 
"result": "Jurassic",
 
"phenomenonTime":  {
   
"start": "2021-13-14T15:16:00Z"
 
}
}

Listing 11 — An Observation for a Datastream defined in the example above

In some cases, a (composite) Sensor generates multiple values that should be kept together. This can be achieved with a DataRecord resultType. In the below example, a temperature and pressure value are stored as a pair, per Observation. The resultType has the SWE-Common class DataRecord, which is a composite class that contains sub-entries. The mandatory fields of a DataRecord are type and fields:

  • The type field defines the type of the result and has the value DataRecord.

  • The fields field is an array of other SWE-Common components. In this example there are two Quantity entries. Each entry has the mandatory fields for a Quantity.

Since there are two distinct definition fields in the resultType, this Datastream must be linked to two ObservedProperties that match the two definitions.

 

{
 
"name": "Temperature and Pressure",
 
"description": "This is a datastream containing temperature and pressure measurement sets.",
 
"resultType": {
   
"type": "DataRecord",
   
"fields": [
     
{
       
"name": "temp",
       
"type": "Quantity",
       
"label": "Air Temperature",
       
"definition": "ObservedProperties(1)",
       
"uom": { "code": "Cel", "label": "degree Celsius", "symbol": "°C"  }
     
},
     
{
       
"name": "press",
       
"type": "Quantity",
       
"label": "Air Pressure",
       
"definition": "ObservedProperties(3)",
       
"uom": { "code": "mbar", "label": "Millibar", "symbol": "mBar"  }
     
}
   
]
 
}
}

Listing 12 — A Datastream example measuring multiple observedProperties

 

{
 
"result": {
   
"temp": 15,
   
"press": 1024
 
},
 
"phenomenonTime": {
   
"start": "2021-13-14T15:16:00Z"
 
}
}

Listing 13 — An Observation for a Datastream defined in the example above

EDITORIAL NOTE

Add MultiDatastream migration example with resultEncoding.

7.7.  Sensor

Requirement 5: Class Sensor

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/sensor
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Sensor entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 12.

B

Each Sensor entity SHALL have the direct relation between a Sensor entity and other entity types listed in Table 13.

A Sensor is an entity that observes a property or phenomenon with the goal of producing an estimate of the value of the property. A Sensor may represent a piece of hardware, but a Sensor may also be a human or an algorithm implemented in sofware.

Table 12 — Attributes of a Sensor entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Sensor entity, commonly a descriptive name.

String

1

definition

The URI linking the Thing to an external definition. Dereferencing this URI SHOULD result in a representation of the definition of the Thing.

URI

0..1

description

The description of the Sensor entity.

String

0..1

encodingType

The encoding type of the metadata property. Its value is one of the ValueCode enumeration (see Table 14 for some suggested ValueCodes)

ValueCode

1

metadata

The detailed description of the Sensor or system. The metadata type is defined by encodingType.

String

1

properties

A JSON Object containing user-annotated properties as key-value pairs

JSON_Object

0..1

Table 13 — Direct relation between a Sensor entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Datastreams

The Datastreams that hold Observations produced by this Sensor.

Datastream

0..*

Table 14 — Non-exhaustive list of code values used for identifying types for the encodingType of the Sensor entity

Sensor encodingTypeValueCode Value
PDFapplication/pdf
SensorMLhttp://www.opengis.net/doc/IS/SensorML/2.0
HTMLtext/html

The Sensor encodingType allows clients to know how to interpret the metadata value. Currently SensorThings API defines two common Sensor metadata encodingTypes. Most sensor manufacturers provide their sensor datasheets in a PDF format. As a result, PDF is a Sensor encodingType supported by SensorThings API. The second Sensor encodingType is SensorML. Lastly, some sensor datasheets are HTML documents rather than PDFs. Other encodingTypes are permitted (e.g., text/plain). Note that the metadata property may contain either a URL to metadata content (e.g., an https://, ftp://, etc. link to a PDF, SensorML, or HTML document) or the metadata content itself (in the case of text/plain or other encodingTypes that can be represented as valid JSON). It is up to clients to perform string parsing necessary to properly handle metadata content.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Sensors/$entity",
 
"@id": "Sensors(1)",
 
"id": 1,
 
"name": "TMP36",
 
"description": "TMP36 - Analog Temperature sensor",
 
"encodingType": "application/pdf",
 
"metadata": "http://example.org/TMP35_36_37.pdf",
 
"Datastreams@navigationLink": "Sensors(1)/Datastreams"
}

Listing 14 — Example of a Sensor entity returned by a HTTP end point.

7.8.  ObservedProperty

Requirement 6: Class ObservedProperty

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/observed-property
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each ObservedProperty entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 15.

B

Each ObservedProperty entity SHALL have the direct relation between an ObservedProperty entity and other entity types listed in Table 16.

An ObservedProperty is a property of a Feature that is being observed by a Sensor, such as temperature, humidity, population count or colour. It should be uniquely identified by its definition, which should point to an external vocabulary by means of a URL, URI or DID.

Table 15 — Attributes of an ObservedProperty entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for ObservedProperty entity, commonly a descriptive name.

String

1

definition

The URI of the ObservedProperty. Dereferencing this URI SHOULD result in a representation of the definition of the ObservedProperty. The definition SHOULD be unique in a service.

URI

1

description

A description about the ObservedProperty.

String

0..1

properties

A JSON Object containing user-annotated properties as key-value pairs

JSON_Object

0..1

Table 16 — Direct relation between an ObservedProperty entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Datastreams

Datastreams that hold Observations that observed this ObservedProperty.

Datastream

0..*

 

{
 
"@context": "https://example.org/v2.0/$metadata#ObservedProperties/$entity",
 
"@id": "ObservedProperties(1)",
 
"id": 1,
 
"name": "DewPoint Temperature",
 
"description": "The dewpoint temperature is the temperature to which the
                  air must be cooled, at constant pressure, for dew to form.
                  As the grass and other objects near the ground cool to
                  the dewpoint, some of the water vapor in the atmosphere
                  condenses into liquid water on the objects."
,
 
"definition": "http://dbpedia.org/page/Dew_point",
 
"Datastreams@navigationLink": "ObservedProperties(1)/Datastreams"
}

Listing 15 — Example of an ObservedProperty entity returned by a HTTP end point.

7.9.  Observation

Requirement 7: Class Observation

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/observation
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Observation entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 17.

B

Each Observation entity SHALL have the direct relation between an Observation entity and other entity types listed in Table 18.

An Observation provides a value for an ObservedProperty of a Feature, as observed by a Sensor. This value can be of any type, as described by the resultType of the Datastream that Observation is associated with.

Table 17 — Attributes of an Observation entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

phenomenonTime

The time instant or period of when the Observation happens.

Note: Many resource-constrained sensing devices do not have a clock. As a result, a client may omit phenomenonTime when POST new Observations, even though phenomenonTime is a mandatory property. When a SensorThings service receives a POST Observations without phenomenonTime, the service SHALL assign the current server time to the value of the phenomenonTime

TM_Object

1

result

The estimated value of an ObservedProperty from the Observation.

ANY

1

resultTime

The time of the Observation’s result was generated

TM_Instant

0..1

validTime

The time period during which the result may be used

TM_Period

0..1

properties

A JSON Object containing user-annotated properties as key-value pairs (usually showing the environmental conditions during measurement)

JSON_Object

0..1

TM_Object is by default encoded as a complex type with a start (mandatory) and end (optional) attributes of type TM_Instant. This means it can either describe a time instant, when only the start is present, or a time interval with both stand and end are present.

TM_Period is by default encoded as a complex type with a start (mandatory) and end (mandatory) attributes of type TM_Instant. This means it always describes a time interval with fixed starting and ending instants.

Table 18 — Direct relation between an Observation entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Datastream

The Datastream this Observation exists in.

Datastream

1

ProximateFeatureOfInterest

The Feature observed by the Observation.

Feature

0..1

An Observation can be directly linked to a Feature, through the relation ProximateFeatureOfInterest. Features linked to an Observation in this way are generally samples, either real, physical ones, like water samples taken from a river, or transient ones, to fix the place that a moving Thing happended to be in, when it made a measurement.

In case the Feature is a domain object, like a river, a building, or a plot of land, the Feature is indirectly linked to the Observation through the UltimateFeatureOfInterest or ProximateFeatureOfInterest relations on the Datastream. It is also possible for all relations to exist, in which case the ProximateFeatureOfInterest of the Observation is a sample of the ProximateFeatureOfInterest of the Datastream, which is, in turn, a part of the UltimateFeatureOfInterest.

A third case is possible, when the target of the observation is (a sub-part of) the Thing itself. For instance, when the Observation is on the battery-level of a drone. In this case neither the ProximateFeatureOfInterest on the Observation, nor the ProximateFeatureOfInterest or UltimateFeatureOfInterest relations on the Datastream need to be set.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Observations/$entity",
 
"@id": "Observations(1)",
 
"id": 1,
 
"phenomenonTime": {
   
"start": "2017-11-12T13:00:00Z",
   
"end": "2017-11-12T14:00:00Z"
 
},
 
"resultTime": "2017-11-12T14:00:00Z",
 
"result": 12.5,
 
"Datastream@navigationLink": "Observations(1)/Datastream",
 
"ProximateFeatureOfInterest@navigationLink": "Observations(1)/ProximateFeatureOfInterest"
}

Listing 16 — Example of an Observation entity returned by a HTTP end point.

7.10.  Feature

Requirement 8: Class Feature

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/feature
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each Feature entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 19.

B

Each Feature entity SHALL have the direct relation between a Feature entity and other entity types listed in Table 20.

An Observation assigns a value to a property of a subject by applying an ObservingProcedure. The subject is the Feature that can take the role of ProximateFeatureOfInterest or UltimateFeatureOfInterest of the Observation [ OGC 20-082r4 and ISO 19156:2023]. In cases where estimating the value of a property of interest is not possible directly, a proxy feature MAY be used. Such an application typically requires taking a sample of the UltimateFeatureOfInterest such that this sample, the ProximateFeatureOfInterest, represents an approximation of the domain feature.

Some examples of features are:

  • The Ultimate Feature of a WiFi enabled thermostat, with a built-in temperature sensor, can be the room that the thermostat monitors. The exact position of the themostat is captured in a Location entity of the Thing representing the thermostat.

  • In the case of water quality monitoring, water samples are taken from a river at a specific sampling location. The water sample, the sampling location and the river are all Features. The river is the UltimateFeatureOfInterest attached to the Datastreams of the Observations taken on the sample. The sampling location is the ProximateFeatureOfInterest attached to the Datastreams of the Observations taken on the sample. Finally, the sample is the ProximateFeatureOfInterest directly attached to the various Observations.

  • In the case of remote sensing, the Feature observed can be the individual geographical parcel or swath that is being sensed, while the Location entity captures the position of the device (drone, sattellite) that hosts the sensors.

Table 19 — Attributes of a Feature entity

NameDefinitionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Feature entity, commonly a descriptive name.

String

1

definition

The URI linking the Feature to an external definition. Dereferencing this URI SHOULD result in a representation of the definition of the Feature.

URI

0..1

description

The description about the Feature

String

0..1

encodingType

The encoding type of the feature property. (see Table 7 for some suggested ValueCodes)

String

1

feature

The detailed description of the feature. The data type is defined by encodingType.

ANY

1

properties

A JSON Object containing user-annotated properties as key-value pairs

JSON_Object

0..1

Table 20 — Direct relation between a Feature entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Observations

All Observations that are made on this Feature

Observation

0..*

DatastreamsProximate

All Datastreams for the Observations of which this Feature is a ProximateFeatureOfInterest.

Datastream

0..*

DatastreamsUltimate

All Datastreams for the Observations of which this Feature is the UltimateFeatureOfInterest.

Datastream

0..*

 

{
 
"@context": "https://example.org/v2.0/$metadata#Features/$entity",
 
"@id": "Features(1)",
 
"id": 1,
 
"name": "0113700020130227",
 
"description": "Water Sample from LA NOYE À DOMMARTIN (80) taken on 2013-02-27 at 10:20:00",
 
"encodingType": "application/geo+json",
 
"feature": {
   
"type": "Point",
   
"coordinates": [
     
2.38961955,
     
49.800951554
   
]
 
},
 
"FeatureType@navigationLink": "Features(1)/FeatureType",
 
"Datastreams@navigationLink": "Features(1)/Datastreams",
 
"Observations@navigationLink": "Features(1)/Observations"
}

Listing 17 — Example of a Feature entity using a GeoJSON Geometry.

 

{
 
"@context": "https://example.org/v2.0/$metadata#Features/$entity",
 
"@id": "Features(2)",
 
"id": 2,
 
"name": "City Center Park",
 
"description": "A public park located in the heart of the city",
 
"encodingType": "application/wkt",
 
"feature": "POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))",
 
"FeatureType@navigationLink": "Features(2)/FeatureType",
 
"Datastreams@navigationLink": "Features(2)/Datastreams",
 
"Observations@navigationLink": "Features(2)/Observations"
}

Listing 18 — Example of a Feature entity using WKT Geometry.

7.11.  FeatureType

Requirement 9: Class FeatureType

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/feature-type
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

Each FeatureType entity SHALL have the mandatory attributes and MAY have the optional attributes listed in Table 21.

B

Each FeatureType entity SHALL have the direct relation between a FeatureType entity and other entity types listed in Table 22.

The type or types of each Feature can be specified using the FeatureType class. The definition attribute of the FeatureType should point to an external registry or code list, that defines the Type.

Table 21 — Attributes of a FeatureType entity

NameDescriptionData TypeMultiplicity

id

A unique, read-only attribute that serves as an identifier for the entity.

ANY

1

name

A property provides a label for Feature entity, commonly a descriptive name.

String

1

definition

The URI the defines this FeatureType. Dereferencing this URI SHOULD result in a representation of the definition of the FeatureType.

URI

0..1

description

The description about the Feature

String

0..1

properties

A JSON Object containing user-annotated properties as key-value pairs

JSON_Object

0..1

Table 22 — Direct relation between a FeatureType entity and other entity types

RoleDescriptionTarget Entity TypeMultiplicity

Features

All Features of a FeatureType.

Feature

0..*

 

{
 
"@context": "https://example.org/v2.0/$metadata#FeatureType/$entity",
 
"@id": "FeatureType(1)",
 
"id": 1,
 
"name": "Water Sample",
 
"description": "A Sample taken from a river, lake or sea",
 
"definition": "https://example.org/water_sample",
 
"Features@navigationLink": "FeatureType(1)/Features"
}

Listing 19 — Example of a FeatureType entity.

7.12.  Integrity

Requirement 10: Class FeatureType

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/integrity
Included inRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
A

For any action that changes data, the service SHALL adhere to the integrity constraints as defined in the data model. When deleting an entity, all related entities that depend on the deleted entity SHALL also be deleted by the service.

For the core model the integrity constraints are summarised in Table 23.

Table 23 — Integrity constraints when changing data

EntityIntegrity Constraints

HistoricalLocation

  • SHALL depend on a Thing entity.

  • SHALL depend on at least one Location entity.

Datastream

  • SHALL depend on a Thing entity.

  • SHALL depend on a Sensor entity.

  • SHALL depend on at least one ObservedProperty entity.

  • The linked ObservedProperties SHALL match the resultType definition.

Observation

  • SHALL depend on a Datastream entity.

8.  Abstract OData API

8.1.  Introduction

This section describes the abstract OData API. The abstract OData API can be implemented using various protocols, like HTTP or MQTT version 5.

Requirements class 2: Abstract API

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req-class/api/abstract
Obligationrequirement
Target typeTarget Type: Abstract API
Conformance classConformance class A.4: http://www.opengis.net/spec/sensorthings/2.0/conf-class/api/abstract
Normative statementsRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Requirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud

8.2.  OData Entity Model

Every OData service utilizes an entity model which MAY be distributed over several schemas. The service describes this model through a metadata document accessible by a simple HTTP GET request to the <serviceRoot>/$metadata path. This chapter describes an overview of the types of entities in the metadata document that will be used to describe the SensorThings API data model and its data model extensions. The entities listed below are also used to describe the REST and MQTT bindings of the SensorThings API service.

This section is base on:

The entity model consists of the following elements:

  • Entity Type: named, structured, keyed element that defines the attributes and relations of Entities. The key of an Entity Type consists of one or more primitive attributes of the Entity Type.

  • Entity: instance of an Entity Type. An Entity can have only one Entity Type.

  • Primitive Type: unnamed, unstructured type, such as String, Integer or DateTime. The full list can be found at: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html#sec_PrimitiveTypes A attribute with a Primitive Type is called a primitive attribute.

  • Complex Type: named, structured, keyless, element consisting of a set of named attributes. Instances of Complex Types can not be accessed outside of the Entity they are contained in. A attribute with a Complex Type is called a complex attribute. Examples of complex types / complex attributes are:

    • TM_Interval (Observation/validTime): The complex type TM_Interval has mandatory declared attributes start and end.

    • TM_Object (Observation/resultTime): The complex type TM_Interval has mandatory declared attribute start and optional declared attribute end.

    • JSON_Object (properties): The complex type JSON_Object is an open type with no declared attributes. That means users can add any attributes they see fit.

  • Relation: named connections between Entities. Relations defined as navigation attributes in Entity Types. Relations have a cardinality.

  • Attributes: named elements that are part of structured types (Entity Types and Complex Types). Attributes can be Primitive-, Complex- or Navigation attributes. Attributes defined as part of a structured type (Entity/Complex Type) are declared attributes. A structured type can allow attributes that are added dynamically, as long as these dynamic attributes do not have the same name as a declared attribute. Structured types that allow dynamic attributes are called Open Types.

  • Entity Set: a named collection of Entities of the same Entity Type. Each Entity is uniquely identified among other Entities in the same Entity Set, by its key. Entity Sets are the entry points into the data model.

  • Annotation: additional information attached to model or instance elements. annotations can be identified by the @ character. If the annotation starts with the @ character, then the annotation pertains to the object containing the annotation. If the annotation has a attribute name before the @ charater, then the annotation pertains the attribute with that name. Annotations are server-generated additional information that a client can use when processing the data. A client can ignore any annotations it does not understand. The default annotations can be found in Table 24. Additional annotations may be defined in the service metadata.

  • EntityId: a globally unique identifier for an Entity. If present in Entity representations, the EntityId is specified in the @id annotation.

Each Entity has a primary key that is composed of one or more of the declared attributes of the entity type. Which attributes of the Entity Type make up the primary key of the Entity Type is specified in the service metadata document. For the data models specified in this document the primary key is always the field id, though the data type of the field may vary between services. In most cases the primary key field will be server generated at the time an Entity is created, but a service may allow for client-specified primary key fields.

URLs in documents may be absolute or relative. Relative URLs are relative to the context URL in the document, or if there is no context url, relative to the request URL. See https://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html#sec_RelativeURLs.

Table 24 — Common control annotations

NameDefinitionData Type

@context

The context url contains the metadata document that describes the context of a payload. See Clause 8.4

URL

@id

The annotation @id is the entity-id, an absolute or relative URL of an entity that uniquely resolves to this entity. This is was known as the @selfLink in SensorThings version 1.

URL

linkName@navigationLink

Annotations of the form linkName@navigationLink are the relative or absolute URL that retrieves the related entity or entities for the navigation attribute linkName.

URL

8.3.  Type Mappings

8.3.1.  Simple Types

Table 25 lists the mapping of types used in the SensorThings API core data model to OData primitive types.

Table 25 — mapping of types used in the SensorThings API core data model to OData primitive types

STA TypeOData typeDescription

ANY

Edm.Untyped

Any primitive or complex type

String

Edm.String

A character string

URI

Edm.String

A character string that must be a valid URI

Geometry

EDM.Geometry

A geometry type

TM_Instant

Edm.DateTimeOffset

A time instant, with timezone information

The SensorThings API core data model contains several complex types. They are TM_Interval, TM_Object and JSON Object.

8.3.2.  Complex Type TM_Interval

TM_Interval is a time interval with a mandatory start and end time. The interval end is “open” meaning that the end-time is not part of the interval.

Table 26 — Attributes of a TM_Interval complex type

NameDescriptionData TypeMultiplicity

start

The starting time (inclusive) of the time interval.

TM_Instant

1

end

The end time (exclusive) of the time interval.

TM_Instant

1

Attributes of the type TM_Interval can be directly compared to other time-related attributes and constants.

8.3.3.  Complex Type TM_Object

TM_Object, used in Observation/phenomenonTime, is either a time instant or a time interval. This is modelled as a time interval with a mandatory start and an optional end time. If the end time is not present, the TM_Object is a time instant. If the end time is present, the TM_Object is a time interval with an “open” end, meaning that the end-time is not part of the interval.

Table 27 — Attributes of a TM_Object complex type

NameDescriptionData TypeMultiplicity

start

The time instant of the time object, or the starting time (inclusive) of the time interval.

TM_Instant

1

end

The end time (exclusive) of the time interval.

TM_Instant

0..1

Filter operators and functions that accept times can work directly on TM_Interval and TM_Object types and will use the start or end time as appropriate. For instance, finding all Observations with a phenomenonTime before 2025-01-01T00:00:00Z can be done using: phenomenonTime lt 2025-01-01T00:00:00Z For phenomenonTimes that are an interval, this will ensure the end of the interval is before the threshold. Users can also filter specifically on the start or end by directly referencing these attributes.

8.3.4.  Complex Type JSON_Object

JSON_Object is an open, complex type with no declared attributes. This means users can store any attributes in instances of this type that they see fit.

8.4.  OData Common Schema Definition Language

The data model is specified in the metadata document that can be retrieved from the context url. It is described in a machine-readable way using the OData Common Schema Definition Language. See https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html

An example CSDL document describing a service hosting a SensorThings API v2.0 core data model can be found in Annex C. A shortened example with comments can be found in Annex B.

8.5.  Encoding rules for constants

Encoding rules for constants in resource paths and query options are listed in Table 28

Table 28 — Encoding rules for constants in requests

TypeDescriptionExample

String

Quoted using single-quotes ('). Single quotes in a string are doubled.

'degree Celsius'
'Abby''s Car'

Number

Numbers are not quoted, use a decimal point (.), no thousands separator.

0.31415926535897931e1
-42

Datetime

Not quoted ISO8601 time with timezone. Special characters (+) must be URL-Encoded.

2012-12-03T07:16:23Z
2012-12-03T07:16:23%2B08:00

Boolean

Literal value true or false

true
false

Null

Literal value null

null

Time Duration

the keyword duration followed by an ISO8601 Druation in single quotes.

duration’P1DT30M'

Geometry

the keyword geography followed by WKT in single quotes.

geography’POINT(-122 43)'

8.6.  URL Patterns

8.6.1.  Introduction

URL Patterns in the SensorThings API consist of four parts: the Service Root, the API version number, the resource path and query options.

The service root URL

the free to chose base path of the service.

The API version number

encoded as: "v" + majorversionnumber + "." + minorversionnumber.

The resource path

consists of zero to many parts separated with by the slash (/) character. Resource paths are case sensitive.

The query options

start with a question mark (?) character. At the top level, query options are separated with the ampersant ( &) character.

 

http://example.org/v2.0/Datastreams(5)/Observations?$orderby=ID&$top=10
__________________/____/__________________________/___________________/
         |          |                |                      |
   service root   version      resource path           query options

Listing 20 — Complete URL example using HTTP bindings

 

base/topic/v2.0/Datastreams(5)/Observations?$orderby=ID&$top=10
__________/____/__________________________/___________________/
    |     version            |                      |
root Topic             resource path           query options

Listing 21 — Complete URL example using MQTT bindings

8.6.2.  Service Document

URL Pattern: <Service Root>/v2.0

Requests to the URL pattern consisting of just the version number, optionally followed by a slash (/) address the service document.

8.6.3.  Service Metadata Document

URL Pattern: <Service Root>/v2.0/$metadata

Requests to the URL pattern consisting of the API version number followed by /$metadata address the service metadata document that describes the data model that the service exposes. The service metadata document is described in Clause 8.4.

8.6.4.  Entity Set

URL Pattern: <Service Root>/v2.0/EntityTypeName

Requests to a URL pattern consisting of the API version number followed by / and the name of an entity type address the set of all entities of the requested type.

 

<Service Root>/v2.0/Datastreams

Listing 22 — Resource pattern for the Datastreams Entity Set

8.6.5.  Entity

URL Pattern: <Service Root>/v2.0/EntityTypeName(<primaryKey>)

Requests to a URL pattern consisting of the name of an EntitySet URL, followed by, in brackets, a primary key value fitting the entity type of the set, address the single Entity from the set, that has the given primary key.

 

<Service Root>/v2.0/Datastreams(4)

Listing 23 — Resource pattern for a specific Datastream, for a service that uses Integers for the id field of Datastreams

 

<Service Root>/v2.0/Datastreams('xz42df')

Listing 24 — Resource pattern for a specific Datastream, for a service that uses Strings for the id field of Datastreams

8.6.6.  Entity Attribute

URL Pattern: <Service Root>/v2.0/EntityTypeName(<primaryKey>)/entityAttribute

Requests to a URL pattern consisting of a URL that addresses an Entity (the base entity), followed by an Entity Attribute, address the value of this Entity Attribute of the base Entity. The used URL for the base entity may itself be a related entity URL.

 

<Service Root>/v2.0/Datastreams(4)/name

Listing 25 — Resource pattern for the name of a specific Datastream

 

<Service Root>/v2.0/Datastreams(4)/Thing/name

Listing 26 — Resource pattern for the name of the Thing of a specific Datastream

8.6.7.  Entity Attribute raw value ($value)

URL Pattern: <Service Root>/v2.0/EntityTypeName(<primaryKey>)/entityAttribute/$value

Requests to a URL pattern consisting of a URL that addresses an Entity (the base entity), followed by an Entity Attribute, followed by /$value, address the raw value of this Entity Attribute of the base Entity. The used URL for the base entity may itself be a related entity URL.

 

<Service Root>/v2.0/Datastreams(4)/name/$value

Listing 27 — Resource pattern for the raw name of a specific Datastream

 

<Service Root>/v2.0/Datastreams(4)/Thing/name/$value

Listing 28 — Resource pattern for the raw name of the Thing of a specific Datastream

8.6.10.  Association link ($ref)

URL Pattern: <Service Root>/v2.0/EntityTypeName(<primaryKey>)/NavigationAttribute/$ref

Requests to a URL pattern consisting of a URL that addresses an Entity (the base entity), followed by a navigation attribute, followed by /$ref, address the entity-id(s) of the related entity or entities of the given navigation attribute.

 

<Service Root>/v2.0/Datastreams(4)/Thing/$ref

Listing 33 — Resource pattern for the association link of the Thing of a specific Datastream

 

<Service Root>/v2.0/Datastreams(4)/Observations/$ref

Listing 34 — Resource pattern for the association link to the Observations related to a specific Datastream

For navigation attribute with a cardinality of many, the navigation attribute may be followed by a primary-key in brackets, to address the specific association between the base entity and the related entity.

 

<Service Root>/v2.0/Datastreams(4)/Observations(1)/$ref

Listing 35 — Resource pattern for the association link between a specific Datastream and a specific Observation

8.6.11.  Nested paths

URL Pattern: <Service Root>/v2.0/EntityTypeName(<primaryKey>)/EntitySetNavigationAttribute(<primaryKey>)

The pattern Clause 8.6.9 and Clause 8.6.5 can be combined to address a specific entity from a related set. This will return a Not Found error when the requested entity is not actually in the related set.

 

<Service Root>/v2.0/Datastreams(4)/Observations(5321)

Listing 36 — Resource pattern for a specific Observation of a specific Datastream

The above example addresses the same entity as <Service Root>/v2.0/Observations(5321), except when Observation 5321 is not actually contained in Datastream 4, since in that case any action on the resource would return a Not Found error.

8.7.  Request Types

To the resources paths above the following request types can be sent:

Read

Read data from the resource path.

Create

Create a new Entity, or new Entities, at the resource path.

Update

Change the Entity or Entities at the resource path. Only the attributes present in the request are updated.

Replace

Replace all the data of the resource with different data.

Delete

Remove the resource.

Execute

Execute an function on a resource.

NOTE:  The Execute request type is not used in the core SensorThings API standard, but may be used in extensions.

8.8.  Additional request parameters

Besides the query options, there are a few other request parameters that are used to convey information between client and server.

Content-Type

Used to indicate the type of the content that is being transferred.

Prefer

Analogous to IETF RFC 7240, used by a client to indicate how it prefers the server to respond to modification requests.

Location

Used by the server to convey the self link of a newly created entity.

8.9.  Requesting Data

8.9.1.  Introduction

This section describes how to read data from a SensorThings API compatible service. Details on how to send requests and how to receive responses are described in the protocol bindings sections. For example, when using the HTTP bindings, GET is used for read requests.

Adapted from:

Requirement 11: Requesting data

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/paths
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support all the read requests listed in section Clause 8.9.2.

8.9.2.  Read Paths

8.9.2.1.  Context URL

Most responses to read requests contain a context URL that describes the content of the payload. The context URL consists of the URL of the service metadata document (See Clause 8.6.3, Clause 8.4) followed by a fragment that identifies the relevant portion of the document.

EDITORIAL NOTE

Explain the @context url. Do we want to go the full complexity? https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_ContextURL

A read Requests to the Service Document URL pattern (Clause 8.6.3) returns the service metadata document as described in Clause 8.4.

8.9.2.2.  Service Document

A read Requests to the Service Document URL pattern (Clause 8.6.2) returns the service document.

The Service document is a JSON object with a attribute named value and a attribute named serverSettings. The content of the attribute named value SHALL be a JSON Array containing one element for each entity set of the SensorThings Service. The content of the attribute named serverSettings SHALL be a JSON Object describing the features the server supports that can not easily be detected by querying the service.

Each element of the value array SHALL be a JSON object with at least two name/value pairs, one with name name containing the name of the entity set (e.g., Things, Locations, etc.) and one with name url containing the URL of the entity set, which may be an absolute or a relative URL. (Adapted from OData 4.01-JSON-Format section 5)

The serverSettings object SHALL contain the attribute conformance of the type Array, containing the URIs of all requirements from this specification and any extensions that the service implements. If a service implements all mandatory requirements from a requirements class, it only needs to list the requirements class id.

The serverSettings object SHALL contain the attribute functions of the type Array, containing the function names of the filter functions that the service implements.

Security extensions can modify the list of requirements to only show those requirements that the user is allowed to use. For example, if a user is not allowed to delete entities, the security extension can hide the create-update-delete/delete-entity requirement. In the most extreme case, a security extension would hide all requirements for a user that is not authenticated, except its own requirement and the instructions on how to authenticate.

Extensions that need to expose additional server settings may do so in a attribute of the serverSettings object that is named after the conformance class URI of the requirement that defines this setting.

 

{
 
"@context": "<Service Root>/v2.0/$metadata",
 
"value": [
   
{
     
"name": "Things",
     
"url": "<Service Root>/v2.0/Things"
   
},
   
{
     
"name": "Locations",
     
"url": "<Service Root>/v2.0/Locations"
   
},
   
{
     
"name": "Datastreams",
     
"url": "<Service Root>/v2.0/Datastreams"
   
},
   
{
     
"name": "Sensors",
     
"url": "<Service Root>/v2.0/Sensors"
   
},
   
{
     
"name": "Observations",
     
"url": "<Service Root>/v2.0/Observations"
   
},
   
{
     
"name": "ObservedProperties",
     
"url": "<Service Root>/v2.0/ObservedProperties"
   
},
   
{
     
"name": "Features",
     
"url": "<Service Root>/v2.0/Features"
   
},
   
{
     
"name": "FeatureTypes",
     
"url": "<Service Root>/v2.0/FeatureTypes"
   
}
 
],
 
"serverSettings": {
   
"conformance": [
       
"http://www.opengis.net/spec/sensorthings/2.0/req/datamodel",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/resource-path/resource-path-to-entities",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/request-data",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/create-entity",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/link-to-existing-entities",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/deep-insert",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/deep-insert-status-code",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/update-entity",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/delete-entity",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-update-delete/historical-location-auto-creation",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/create-observations-via-mqtt/observations-creation",
       
"http://www.opengis.net/spec/sensorthings/2.0/req/receive-updates-via-mqtt/receive-updates"
   
],
   
"functions": [
     
"any","cast","ceiling","concat","endswith","floor","floor","geo.distance","geo.intersects","geo.length",
     
"indexof","interval","length","now","round","round","startswith","st_contains","st_crosses","st_disjoint",
     
"st_equals","st_intersects","st_overlaps","st_relate","st_touches","st_within","substring","substringof",
     
"tolower","toupper","trim"
   
],
   
"http://www.opengis.net/spec/sensorthings/2.0/req/bindings/mqtt": {
     
"endpoints": [
       
"mqtt://server.example.com:1833",
       
"ws://server.example.com/sensorThings",
     
]
   
}
 
}
}

Listing 37 — An example service document.

EDITORIAL NOTE

Update example with the correct requirement URLs.

8.9.2.3.  EntitySet

When a Read request is made to a URI pattern that addresses an entity set (Clause 8.6.4, Clause 8.6.9), the service returns a JSON object with the attributes @context and value and optionally @count and @nextLink. The @context annotation SHALL be a context URI as described in Clause 8.9.2.1. The value of the value attribute SHALL be an array containing entities in the specified entity set, or an empty array if there are no entities in the addressed set. The @count annotation SHALL, if returned by default, or requested explicitly, contain the total number of items in the set that match the request, as described in Clause 8.9.3.6. If service-driven pagination is in effect, the @nextLink annotation SHALL contain a link to the next set of entities, as described in Clause 8.9.3.12.

Read requests to an entity set can use all query options: $filter, $count, $orderby, $skip, $top, $expand, $select and $format.

 

{
 
"@context": "<Service Root>/v2.0/$metadata#ObservedProperties",
 
"@count": 36,
 
"value": [
   
{
     
"@id": "<Service Root>/v2.0/ObservedProperties(1)",
     
"id": 1,
     
"name": "SO2",
     
"definition": "http://dd.eionet.europa.eu/vocabulary/aq/pollutant/1",
     
"description": "SO2",
     
"properties": {
       
"eionetId": 1,
       
"owner": "http://dd.eionet.europa.eu",
       
"recommendedUnit": "µg/m3"
     
},
     
"Datastreams@navigationLink": "<Service Root>/v2.0/ObservedProperties(1)/Datastreams"
   
},
   
{
     
"@id": "<Service Root>/v2.0/ObservedProperties(2)",
     
"id": 2,
     
"name": "PM2.5",
     
"definition": "http://dd.eionet.europa.eu/vocabulary/aq/pollutant/6001",
     
"description": "PM2.5",
     
"properties": {
       
"eionetId": 6001,
       
"owner": "http://dd.eionet.europa.eu",
       
"recommendedUnit": "µg/m3"
     
},
     
"Datastreams@navigationLink": "<Service Root>/v2.0/ObservedProperties(2)/Datastreams"
   
}, { }, { }, { }
 
],
 
"@nextLink": "<Service Root>/v2.0/ObservedProperties?$top=5&$skip=5"

}

Listing 38 — Possible result from a read request to an Entity Set resource returning ObservedProperties, with $top=5 and $count=true

8.9.2.4.  Single Entity

When a Read request is made to a URI pattern that addresses a single entity (Clause 8.6.5, Clause 8.6.8), the service returns a JSON object representing the entity, with the added attributes @context. The @context annotation SHALL be a context URI as described in Clause 8.9.2.1.

Read requests to a URI pattern that returns a single entity can use the $expand, $select and $format query options.

 

{
 
"@context": "<Service Root>/v2.0/$metadata#Things/$entity",
 
"@id": "<Service Root>/v2.0/Things(1)",
 
"id": 1,
 
"name": "Oven",
 
"description": "This thing is an oven.",
 
"properties": {
   
"owner": "Noah Liang",
   
"color": "Black"
 
},
 
"HistoricalLocations@navigationLink": "<Service Root>/v2.0/Things(1)/HistoricalLocations",
 
"Locations@navigationLink": "<Service Root>/v2.0/Things(1)/Locations",
 
"Datastreams@navigationLink": "<Service Root>/v2.0/Things(1)/Datastreams"
}

Listing 39 — Possible result from a request to an Entity resource returning a Thing

8.9.2.5.  Single Entity Attribute

When a Read request is made to a URI pattern that addresses a single entity attribute (Clause 8.6.6), the service returns the JSON representation of this entity attribute.

 

{
 
"@context": "<Service Root>/v2.0/$metadata#Edm.String",
 
"value": "Oven"
}

Listing 40 — Possible result from a request to an Entity resource returning the name of a Thing

8.9.2.6.  Raw Value of a Single Entity Attribute

When a Read request is made to a URI pattern that addresses the raw value of a single entity attribute (Clause 8.6.7), the service returns the entity attribute.

 

Oven

Listing 41 — Possible result from a request to an Entity resource returning the raw value of the name of a Thing

8.9.2.7.  Relation Reference

When a Read request is made to a URI pattern that addresses a relation reference (Clause 8.6.10), the service responds with the entity-id(s) of the target Entity(s).

 

{
 
"@context": "<Service Root>/v2.0/$metadata#$ref",
 
"@id": "<Service Root>/v2.0/Things(42)"
}

Listing 42 — Response to a read request for <Service Root>/v2.0/Datastream(10643)/Thing

 

{
 
"@context": "http://host/service/$metadata#Collection($ref)",
 
"value": [
   
{ "@id": "<Service Root>/v2.0/Datastreams(10643)" },
   
{ "@id": "<Service Root>/v2.0/Datastreams(10759)" }
 
]
}

Listing 43 — Response to a read request for <Service Root>/v2.0/Things(42)/Datastreams

 

{
 
"@context": "<Service Root>/v2.0/$metadata#$ref",
 
"@id": "<Service Root>/v2.0/Locations(1)"
}

Listing 44 — Response to a read request for <Service Root>/v2.0/Things(1)/Locations(1)

8.9.3.  Request Query Options

8.9.3.1.  Introduction

Read requests can be modified using various query options. Query options are added to the URL of the request, as specified in Clause 8.6.

8.9.3.2.  Evaluation Order

The OGC SensorThings API adapts many of OData’s system query options and their usage. These query options allow refining the request. The result of the service request is as if the system query options were evaluated in the following order.

Prior to applying any server-driven pagination:

  • $filter

  • $count

  • $orderby

  • $skip

  • $top

After applying any server-driven pagination:

  • $expand

  • $select

  • $format

Requirement 12: Requesting data

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/precedence
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL evaluate the query options supported, in the order defined in section Clause 8.9.3.2.

8.9.3.3.  $select

The $select system query option requests the service to return only the attributes explicitly requested by the client. The value of a $select query option SHALL be a comma-separated list of selection clauses. Each selection clause SHALL be a attribute name (including navigation attribute names). For navigation attributes, $select controls the inclusion of the navigationLink in the response.

In the response, the service SHALL return the specified content, if available. Expanded navigation attributes do not need to be added to the $select list, they SHALL always be included in the response. The $select option can be applied to any request that returns an Entity or an EntitySet.

Note: Adapted from OData 4.01-Protocol 11.2.5.1

 



v2.0/Things?$select=id,name

Listing 45 — Resource pattern returning only the id and name of the Entities in the Things EntitySet.

Requirement 13: Select

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/select
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $select query option as described in section Clause 8.9.3.3.

8.9.3.4.  $select distinct

It is quite useful to give Entities common attributes, like a “type”. But when filtering on such a common attribute the client needs to know what the used values are. Distinct select allows a client to request all distinct values for a field or a set of fields.

Distinct select can be used in expands, and can be ordered. When combining $orderby with a distinct select, it is only possible to order by the exact fields that are selected.

Note that selecting distinct values for the primary key field (id) makes no sense, since this field is unique for each entity.

To request the distinct values for a set of selected fields, add the distinct: keyword at the start of the $select parameter.

The returned data is formatted just like a non-distinct request of the same type would be.

 

v2.0/Things?$select=distinct:properties/type

Listing 46 — request returning all distinct values of the properties/type field of all Things

 

{
   
"value": [
       
{ "properties": { "type": "waterBody" } },
       
{ "properties": { "type": "station" } },
       
{ "properties": { "type": "aquifer" } }
   
]
}

Listing 47 — possible response to the above request

Requirement 14: Select Distinct

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/select_distinct
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

If a service advertises this requirement in the service document then the service SHALL support the distinct: keyword in the $select query option as described in section Clause 8.9.3.4.

8.9.3.5.  $expand

The $expand system query option indicates the related entities to be represented inline. The value of the $expand query option SHALL be a comma separated list of navigation attribute names. Query options can be applied to the expanded navigation attribute by appending a semicolon ( ;) separated list of query options, enclosed in parentheses, to the navigation attribute name. Allowed system query options are $filter, $select, $orderby, $skip, $top, $count, and $expand.

Expanded navigation attributes do not need to be added to $select, they are implicitly selected.

The $expand option can be applied to any request that returns an Entity or an EntitySet.

Note: Adapted from OData 4.01-Protocol 11.2.5.2

 

v2.0/Things?$expand=Datastreams($expand=ObservedProperty)

Listing 48 — Resource pattern returning Things, with their Datastreams, and the ObservedProperty for each Datastream.

 

v2.0/Datastreams?$expand=Observations($select=result,phenomenonTime;$orderby=phenomenonTime desc;$top=1),ObservedProperty

Listing 49 — Resource pattern returning Datastream as well as the result and phenomenonTime of the last Observation (as ordered by phenomenonTime) and the ObservedProperty associated with this Datastream.

Requirement 15: Expand

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/expand
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $expand query option as described in section Clause 8.9.3.5.

8.9.3.6.  $top

The $top system query option specifies the limit on the number of items returned from an EntitySet. The value of the $top system query option SHALL be a non-negative integer. The service SHALL return the number of available items up to but not greater than the specified value.

If no unique ordering is imposed through an $orderby query option, the service SHALL impose a stable ordering across requests that include $top.

In addition, if the $top value exceeds the service-driven pagination limitation (i.e., the largest number of entities the service can return in a single response), the $top query option SHALL be discarded and the server-side pagination limitation SHALL be imposed.

Note: Adapted from OData 4.01-Protocol 11.2.6.3

 

v2.0/Things?$top=5

Listing 50 — Resource pattern returning only the first five entities in the Things EntitySet.

 

v2.0/Observations?$top=5&$orderby=phenomenonTime desc

Listing 51 — Resource pattern returning the first five Observation entries after sorting by the phenomenonTime attribute in descending order.

Requirement 16: Top

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/top
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $top query option as described in section Clause 8.9.3.6.

8.9.3.7.  $skip

The $skip system query option specifies the number for the items of the queried EntitySet that SHALL be excluded from the result. The value of $skip system query option SHALL be a non-negative integer n. The service SHALL return items starting at position n+1. If no unique ordering is imposed through an $orderby query option, the service SHALL impose a stable ordering across requests that include $skip.

Note: Adapted from OData 4.01-Protocol 11.2.6.4

 

v2.0/Things?$skip=5

Listing 52 — Resource pattern returning Thing entities starting with the sixth Thing entity in the Things EntitySet.

 

v2.0/Observations?$skip=2&$top=2&$orderby=resultTime

Listing 53 — Resource pattern returning the third and fourth Observation entities from the collection of all Observation entities when the collection is sorted by the resultTime attribute in ascending order.

Requirement 17: Skip

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/skip
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $skip query option as described in section Clause 8.9.3.7.

8.9.3.8.  $count

The $count system query option with a value of true specifies that the total count of items within an EntitySet matching the request SHALL be returned along with the result. A $count query option with a value of false specifies that the service SHALL not return a count.

The service SHALL reject the request and inform the client that the request is malformed if a value other than true or false is specified.

The $count system query option SHALL ignore any $top, $skip, or $expand query options, and SHALL return the total count of results across all pages including only those results matching any specified $filter.

Clients should be aware that the count returned inline may not exactly equal the actual number of items returned, due to latency between calculating the count and enumerating the last value or due to inexact calculations on the service.

For requests to an EntitySet, the count is returned in the @count attribute of the returned object. When a count is requested on an expanded EntitySet, the count is returned in the <navigationlink name>@count attribute of the containing Entity.

Note: Adapted from OData 4.01-Protocol 11.2.6.5

Requirement 18: Count

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/count
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $count query option as described in section Clause 8.9.3.8.

8.9.3.9.  $orderby

The $orderby system query option specifies the order in which items are returned from the service. The value of the $orderby system query option SHALL contain a comma-separated list of expressions whose primitive result values are used to sort the items. A special case of such an expression is a attribute path terminating on a primitive attribute.

The expression MAY include the suffix asc for ascending or desc for descending, separated from the attribute name by one or more spaces. If asc or desc is not specified, the service SHALL order by the specified attribute in ascending order.

Null values SHALL come before non-null values when sorting in ascending order and after non-null values when sorting in descending order.

Items SHALL be sorted by the result values of the first expression, and then items with the same value for the first expression SHALL be sorted by the result value of the second expression, and so on.

Note: Adapted from OData 4.01-Protocol 11.2.6.2

 

v2.0/Observations?$orderby=result

Listing 54 — Resource pattern returning all Observations ordered by the result attribute in ascending order.

 

v2.0/Observations?$orderby=Datastreams/id desc, phenomenonTime

Listing 55 — Resource pattern returning all Observations ordered by the id attribute of the linked Datastream entry in descending order, then by the phenomenonTime attribute of Observations in ascending order.

Requirement 19: Order By

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/orderby
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $count query option as described in section Clause 8.9.3.9.

8.9.3.10.  $filter

8.9.3.10.1.  Introduction

The $filter option can be used to filter the entities returned by a request to any EntitySet. The expression specified with $filter is evaluated for each entity in the collection, and only items where the expression evaluates to true SHALL be included in the response. Entities for which the expression evaluates to false or to null, or which reference attributes that are unavailable due to permissions, SHALL be omitted from the response.

The expression language that is used in $filter operators SHALL support references to attributes and literals. The literal values SHALL be strings enclosed in single quotes, numbers, boolean values (true or false), null, datetime values as ISO 8601 time string, duration values or geometry values. Encoding rules for constants are listed in Table 28 Attributes of Entities are addressed by their name.

Note: Adapted from OData 4.01-Protocol 11.2.6.1

 

v2.0/Datastreams(42)/Observations?$filter=result gt 5

Listing 56 — Observations of Datastream 42 that have a result greater than 5.

 

v2.0/Locations?$filter=st_within(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')

Listing 57 — Locations inside a given area.

Sub-proprties of complex attributes are addressed using the complex attribute name, followed by a /, followed by the sub-attribute name.

 

v2.0/Observations?$filter=validTime/start lt 2012-12-03T07:16:23Z

Listing 58 — Observations with a valid time that started before the given timestamp.

Entities can be filtered on attributes of related entities by using the navigationAttribute, followed by a /, followed by a attribute of the related entity. This can be used recursively. For filtering on attributes of entities in a related EntitySet see the any() function.

 

v2.0/Observations?$filter=Datastream/name eq 'Temperature'

Listing 59 — Observations of all Datastreams that are named Temperature.

 

v2.0/Observations?$filter=Datastream/Thing/name eq 'House 1'

Listing 60 — Observations of all Things that are named House 1.

8.9.3.10.2.  Built-in filter operations

The OGC SensorThings API supports a set of built-in filter operations, as described in the following table. These built-in filter operator usages and definitions follow the [OData Version 4.01. Part 1: Protocol 11.2.6.1.1] and [OData Version 4.01 ABNF]. The operator precedence is described in [OData Version 4.01. Part 2: URL Conventions Section 5.1.1.17].

Table 29 — Built-in Filter Operators

OperatorDescriptionExample
Comparison Operators
eqEqual

/Datastreams?$filter=resultType/type eq 'Quantity'

neNot equal

/Datastreams?$filter=resultType/type ne 'Quantity'

gtGreater than

/Observations?$filter=result gt 20.0

geGreater than or equal

/Observations?$filter=result ge 20.0

ltLess than

/Observations?$filter=result lt 100

leLess than or equal

/Observations?$filter=result le 100

inContainment
  • /Things?$filter=properties/type in ('Room','Corridor')
    Where properties/type is a string.

  • /Things?$filter='Vehicle' in properties/tags
    Where proprties/tags is an array of strings.

Logical Operators
andLogical and

/Observations?$filter=result le 3.5 and FeatureOfInterest/id eq 1

orLogical or

/Observations?$filter=result gt 20 or result le 3.5

notLogical negation

/Things?$filter=not startswith(description,'test')

Arithmetic Operators
addAddition
  • /Observations?$filter=result add 5 gt 10

  • /Observations?$filter=validTime gt now() add duration'PT1H'

subSubtraction
  • /Observations?$filter=result sub 5 gt 10

  • /Observations?$filter=phenomenonTime gt now() sub duration'P1D'

mulMultiplication

/Observations?$filter=result mul 2 gt 2000

divDivision

/Observations?$filter=result div 2 gt 4

modModulo

/Observations?$filter=result mod 2 eq 0

Grouping Operators
( )Precedence grouping

/Observations?$filter=(result sub 5) mul 2 gt 10

8.9.3.10.3.  Built-in query functions

The OGC SensorThings API supports a set of functions that can be used with the $filter or $orderby query operations. The following table lists the available functions and they follows the OData Canonical function definitions listed in OData Version 4.01 Part 2: URL Conventions, Section 5.1.1.4.

In order to support spatial relationship functions, SensorThings API defines nine additional geospatial functions based on the spatial relationship between two geometry objects. The spatial relationship functions are defined in the OGC Simple Feature Access specification [OGC 06-104r4 part 1, clause 6.1.2.3]. The names of these nine functions start with a prefix st_ following the OGC Simple Feature Access specification [OGC 06-104r4]. In addition, the Well-Known Text (WKT) format is the default input geometry for these nine functions.

In some cases the service may not have enough information to deduce the types of parameters used in functions. This may, for instance, happen when combining two values from json objects, or attributes of type ANY. In such cases, the cast function can be used.

Table 30 — Built-in Query Functions

FunctionDefinitionExample

String Functions

contains

bool contains(string p0, string p1)

contains(description, 'Sensor Things')

substringof

bool substringof(string p0, string p1)

substringof('Sensor Things',description)

endswith

bool endswith(string p0, string p1)

endswith(description,'Things')

startswith

bool startswith(string p0, string p1)

startswith(description,'Sensor')

length

int length(string p0)

length(description) eq 13

indexof

int indexof(string p0, string p1)

indexof(description,'Sensor') eq 1

substring

  • string substring(string p0, int p1)

  • string substring(string p0, int p1, int p2)

  • substring(description,1) eq 'ensor Things'

  • substring(description,2,4) eq 'nsor'

tolower

string tolower(string p0)

tolower(description) eq 'sensor things'

toupper

string toupper(string p0)

toupper(description) eq 'SENSOR THINGS'

trim

string trim(string p0)

trim(description) eq 'Sensor Things'

concat

string concat(string p0, string p1)

concat(concat(unitOfMeasurement/symbol,', '), unitOfMeasurement/name) eq 'degree, Celsius'

Date Functions

now

Edm.DateTimeOffset now()

resultTime ge now()

interval

TM_Interval interval(start, end or duration)

interval(properties/referenceTime, duration'PT1H')

Math Functions

round

int round(number p0)

round(result) eq 32

floor

int floor(number p0)

floor(result) eq 32

ceiling

int ceiling(number p0)

ceiling(result) eq 33

Geospatial Functions

geo.distance

double geo.distance(Point p0, Point p1)

geo.distance(location, geography'POINT (30 10)')

geo.length

double geo.length(LineString p0)

geo.length(geography'LINESTRING (30 10, 10 30, 40 40)')

geo.intersects

bool geo.intersects(Point p0, Polygon p1)

geo.intersects(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')

Spatial Relationship Functions

st_equals

bool st_equals(geography p0, geography p1)

st_equals(location, geography'POINT (30 10)')

st_disjoint

bool st_disjoint(geography p0, geography p1)

st_disjoint(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')

st_touches

bool st_touches(geography p0, geography p1)

st_touches(location, geography'LINESTRING (30 10, 10 30, 40 40)')

st_within

bool st_within(geography p0, geography p1)

st_within(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')

st_overlaps

bool st_overlaps(geography p0, geography p1)

st_overlaps(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))')

st_crosses

bool st_crosses(geography p0, geography p1)

st_crosses(location, geography'LINESTRING (30 10, 10 30, 40 40)')

st_intersects

bool st_intersects(geography p0, geography p1)

st_intersects(location, geography'LINESTRING (30 10, 10 30, 40 40)')

st_contains

bool st_contains(geography p0, geography p1)

st_contains(location, geography'POINT (30 10)')

st_relate

bool st_relate(geography p0, geography p1, string p2)

st_relate(location, geography'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))', 'T********')

Collection Functions

any

bool EntitySetNavProp/any(name: expression)

Observations/any(o: o/result gt 5 and o/phenomenonTime gt 2024-01-01T00:00:00Z)

Type Functions

cast

type cast(expression,typeName)

cast(result,Edm.Decimal) gt cast(Datastream/properties/threshold,Edm.Decimal)

8.9.3.10.4.  Any

The any() function applies a boolean expression to each member of a collection and returns true if the expression returns true for any member of the collection. The any function can be used by adding a slash and the any keyword after a filter path ending in an EntitySet. The argument of the any function is a case-sensitive, alphanumeric lamda variable name, followed by a colon ( :), followed by a boolean expression that can use the defined variable to access attributes of the entities in the collection.

Path expressions not prefixed by the lambda variable are evaluated in the context of the collection that is the target of the $filter containing the any function.

 

Datastreams?$filter=Observations/any(o: o/result gt properties/threshold and o/phenomenonTime gt 2024-01-01T00:00:00Z)

Listing 61 — Request for all Datastreams that have at least one Observation that has both a result greater than the threshold custom attribute in the containing Datastream, and a phenomenonTime after 2024-01-01 00:00:00Z

In the example above, the properties/threshold path is evaluated in the context of the Datastreams collection being filtered.

 

Things?$filter=Datastreams/any(d1: d1/ObservedProperty/name eq 'NO2') and Datastreams/any(d2: d2/ObservedProperty/name eq 'O3')

Listing 62 — Request for all Things that have both a Datastream measuring NO2 and a Datastream measuring O3

Requirement 20: Format

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/filter
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
A

A service SHALL support the $filter query option as described in section Clause 8.9.3.10.

B

A service SHALL list the suppored filter function in the service document as described in section Clause 8.9.2.2.

8.9.3.11.  $format

8.9.3.11.1.  Introduction

The format of the data returned by read request can be controlled with the $format query option. The default value for the $format option is application/json.

Requirement 21: Format

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/format
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support the $format query option as described in section Clause 8.9.3.11 and the JSON format described in Clause 8.9.3.11.2.

8.9.3.11.2.  application/json

This formatter encodes responses in JSON as specified in OData JSON Format Version 4.01. The JSON format can be explicitly requested using the $format query option with a value of application/json, or the shorter alias json. The format option allows for the format parameter metadata to control the amount of service metadata added to the response.

  • $format=application/json;metadata=full returns the full metadata.

  • $format=application/json;metadata=minimal removes all metadata that can be calculated by the client, returning only: context, count (if requested) and nextLink (if applicable)

  • $format=application/json;metadata=none only returns: nextLink (if applicable) and count (if requested)

8.9.3.12.  Server driven pagination

Responses that include only a partial set of the items identified by the request URL SHALL contain a link that allows retrieving the next partial set of items. This link is called a nextLink; its representation is format-specific. The final partial set of items (the last page) SHALL NOT contain a nextLink.

The nextLink annotation indicates that a response is only a subset of the requested collection of entities or collection of entity references. It contains a URL that allows retrieving the next subset of the requested collection.

SensorThings clients SHALL treat the URL of the nextLink as opaque, and SHALL NOT append system query options to the URL of a next link. Services may disallow a change of format on requests for subsequent pages using the next link.

Note: Adapted from OData 4.01-Protocol 11.2.6.7

Requirement 22: Format

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/pagination
Included inRequirements class 3: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/read
Statement

A service SHALL support pagination as described in section Clause 8.9.3.12.

8.10.  Modifying Data

8.10.1.  Introduction

This section describes how to create, update and delete Entities. Details on how to send create, update and delete requests and how responses are received are described in the protocol bindings sections.

The content type of data sent to a service must be application/json, unless otherwise specified.

Requirement 23: Create, Update, Delete

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/advertisement
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL advertise the requirements class http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud in its service document.

8.10.2.  Creating Entities

Entities can be created with a create request to an URI pattern that addresses an entity set (Clause 8.6.4 or Clause 8.6.9). The content of the create request is the JSON encoded representation of the entity to be created.

If the inline representation contains a value for a computed attribute (i.e., id), the service ignores that value when creating the entity.

When the URI pattern is of the related entity set type (Clause 8.6.9), the created entity is automatically linked to the parent entity of the entity set the create request is sent to.

Relations to existing entities can be created by providing the entity-id (selfLink) of the existing entities. If a conflicting value for a relation exists in the URI and the content of the request, the value from the URI takes priority.

 



{
 
"name": "Oven temperature",
 
"description": "This is a datastream measuring the air temperature in an oven.",
 
"resultType": {
   
"type": "Quantity",
   
"label": "Oven temperature",
   
"definition": "ObservedProperties(1)",
   
"uom": { "code": "Cel", "label": "degree Celsius", "symbol": "°C" }
 
},
 
"Sensor": {"@id": "Sensors(2)"}
}

Listing 63 — Sending a create request to v2.0/Things(5)/Datastreams with the given content will create a Datastream, linked to Thing 5, Sensor 2 and the ObservedProperty that matches the definition in the resultType.

Requirement 24: Creating Entities

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/create
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL support creating entities as described in section Clause 8.10.2.

8.10.3.  Deep Insert

A create request can have related entities embedded in-line, to be created alongside the main entity. Such a create request is referred to as a “deep insert”.

On success, the service creates all entities and relates them. On failure, the service does not create any of the entities.

 



{
 
"description": "This an oven with a temperature datastream.",
 
"name": "oven",
 
"Locations": [
   
{
     
"name": "CCIT",
     
"description": "Calgary Centre for Innovative Technologies",
     
"encodingType": "application/geo+json",
     
"location": {
       
"type": "Feature",
       
"geometry": {
         
"type": "Point",
         
"coordinates": [10,10]
       
}
     
}
   
}
 
],
 
"Datastreams": [
   
{
     
"name": "oven temperature",
     
"description": "This is a datastream for an oven’s internal temperature.",
     
"resultType": {
       
"type": "Quantity",
       
"label": "Oven temperature",
       
"definition": "ObservedProperties(1)",
       
"uom": { "code": "Cel", "label": "degree Celsius", "symbol": "°C" }
     
},
     
"Sensor": {
       
"name": "DS18B20",
       
"description": "DS18B20 is an air temperature sensor…",
       
"encodingType": "application/pdf",
       
"metadata": "http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf"
     
}
   
}
 
]
}

Listing 64 — Sending a create request to v2.0/Things with the given content will create a Thing with its Location and a Datastream with an associated Sensor. The Datastream will automatically be linked to the ObservedProperty that matches the definition in the resultType.

Requirement 25: Deep Insert

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/deep_insert
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL support creating entities as described in section Clause 8.10.3.

8.10.4.  Updating Entities

Entities can be updated with an update request to an URI pattern that addresses a single entity (Clause 8.6.5 or Clause 8.6.8).

An update request must contain as content only those updatable attributes of the entity that are to be changed. Attributes that are not present in the update request are not changed, though server-generated attributes may be updated by the server as a result of the change request.

For even finer grained update control, or updates that are safe from concurrent modification by other users, see Clause 8.10.7.

 



{
 
"name": "My Updated Oven"
}

Listing 65 — Sending an update request to v2.0/Things(1) with the given content will update the name of Thing 1, and leave all other fields unchanged.

Requirement 26: Updating Entities

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/update
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL support updating entities as described in section Clause 8.10.4.

8.10.5.  Replacing Entities

Entities can be replaced with a replace request to an URI pattern that addresses a single entity (Clause 8.6.5 or Clause 8.6.8).

A replace request must contain as content the complete entity to be replaced. Entity attributes that are not present in the replace request are removed from the entity. Navigation attributes are not affected.

 



{
 
"name": "My Updated Oven"
}

Listing 66 — Sending a replace request to v2.0/Things(1) with the given content will update the name of Thing 1, and remove all other fields.

Requirement 27: Replacing Entities

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/replace
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service advertising this requirements in its service document SHALL support replacing entities as described in section Clause 8.10.5.

8.10.6.  Deep Update

The content of an update request may contain nested entites to be updated or created and entity references to be linked, that specify the full set of entities to be linked.

On succes, the server makes all the changes. On failure, the server makes none of the changes.

The server must ensure data integrity and return an error if the update would break integrity. For example, an update request that specifies fewer Datastreams on a Thing than the Thing currently has can not be valid, since a Datastream MUST have a Thing. To remove a Datastream from a Thing, either the Datastream must be explicitly deleted, or linked to a different Thing.

 



{
 
"name": "My Updated Oven",
 
"Locations": [
   
{
     
"name": "New Location of my Oven",
     
"description": "It fits much better here",
     
"encodingType": "application/geo+json",
     
"location": {
       
"type": "Point",
       
"coordinates": [-114.061,51.051]
     
}
   
},
   
{
     
"@id": "Locations(1)"
   
}
 
]
}

Listing 67 — Sending an update request to v2.0/Things(1) with the given content will update the name of Thing 1, create a new Location, and set the Locations of the Thing to the newly created Location and existing Location 1, removing any old Location(s).

Requirement 28: Deep Update

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/deep_update
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service advertising this requirements in its service document SHALL support the deep updating of entities as described in section Clause 8.10.6.

8.10.7.  JSON-Patch

Services MAY additionally support JSON PATCH format IETF RFC 6902 to express a sequence of operations to apply to a SensorThings entity.

Entities can be updated with a json-patch request to an URI pattern that addresses a single entity (Clause 8.6.5 or Clause 8.6.8).

The content-type of the data in a json-patch request is application/json-patch+json.

The paths in the json-patch request must not contain navigation attributes.

 



[
 
{ "op": "test", "path": "/properties/status", "value": "inactive" },
 
{ "op": "replace", "path": "/properties/status", "value": "active" }
]

Listing 68 — Sending a json-patch request to v2.0/Things(1) with the given content will set the value of properties/status to active only if the current value of properties/status to inactive and return a Conflict error otherwise.

Requirement 29: JSON-Patch

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/json_patch
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service advertising this requirements in its service document SHALL support the updating of entities with JSON-Patch requests as described in section Clause 8.10.7.

8.10.8.  Return Value

The returned value for an entity modification request depends on the prefer request parameter, with the possible values return=minimal (default) and return=representation.

If the prefer request parameter is not present, or does not contain a value for return, or has return=minimal then, for create requests, the entity-id (selfLink) of the created entity is returned as a value, and no content is returned. For update requests no content is returned.

If the prefer request parameter has return=representation, then the created or updated resource is returned, optionally taking $expand, $select and $format query options into account.

Requirement 30: Return Value

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/return_value
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL return data to modification requests as described in section Clause 8.10.8.

8.10.9.  Modifying Relations

Single-valued navigation attributes (Clause 8.6.8) can be updated by sending a replace request to the association link (Clause 8.6.10). The replace request must contain an entity reference to the single entity that should be the new target of the navigation attribute.

 



replace http://host/service/Datastreams(1)/UltimateFeatureOfInterest/$ref
  {"id": "Feature(2)"}

Listing 69 — Example of a request setting the UltimateFeatureOfInterest of Datastream 1 to Feature 2.

Single-valued navigation attributes can be un-linked by sending a delete request to the association link. This will not remove the entities, only remove the link between the entities.

 



delete http://host/service/Datastreams(1)/UltimateFeatureOfInterest/$ref

Listing 70 — Example of a request removing the UltimateFeatureOfInterest from Datastream 1.

EntitySet navigation attributes (Clause 8.6.9) can be extended with a new link to an existing entity by sending a create request to the association link of the navigation attribute. The create request must contain an entity reference to the single entity that should be added to the set of related entities.

 



create http://host/service/Feature(1)/FeatureTypes/$ref
  {"id": "FeatureTypes(3)"}

Listing 71 — Example of a request adding FeatureType 3 as FeatureType of Feature 1.

The complete list of relations in an EntitySet-type navigation attribute can be replaced by sending a replace request to the association link of the navigation attribute. The replace request must contain a list of entity references, like the one returned by a read request to the association link of the navigation attribute.

 



replace http://host/service/Feature(1)/FeatureTypes/$ref
  {"value": [
    {"id": "FeatureTypes(1)"},
    {"id": "FeatureTypes(2)"}
  ]}

Listing 72 — Example changing the set of FeatureTypes of Feature 1 to contain exactly FeatureType 1 and FeatureType 2.

A single relation can be removed from an EntitySet-type navigation attribute by either sending a delete request to the association link of the relation, or by sending a delete request to the association link of the navigation attribute, with an $id parameter specifying the self-link (absolute or relative) of the target Entity.

 



delete http://host/service/Feature(1)/FeatureTypes(2)/$ref
delete http://host/service/Feature(1)/FeatureTypes/$ref?$id=../../FeatureTypes(2)

Listing 73 — Examples of the two ways to remove FeatureType 2 from an EntitySet-typed navigation attribute FeatureTypes of Feature 1.

All relations can be removed from an EntitySet-type navigation attribute by sending a delete request to the association link of the navigation attribute.

 



delete http://host/service/Feature(1)/FeatureTypes/$ref

Listing 74 — Example removing all FeatureTypes from Feature 1.

For any change of relations data integrity MUST be maintained. If a request would break data integrity then an INVALID REQUEST error is returned. On a succesful change, the server returns an empty response.

Requirement 31: Modifying Relations

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/update_relations
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL support relation-modification requests as described in section Clause 8.10.9.

8.10.10.  Deleting Entities

Entities can be removed from a service by sending a delete request to an URI pattern that addresses a single entity (Clause 8.6.5 or Clause 8.6.8).

Services SHALL implicitly remove relations to and from an entity when deleting it; clients need not delete the relations explicitly.

The server must ensure data integrity, and delete any entities that depend on the entity being deleted. For example, deleting a Thing would also delete the HistoricalLocations and Datastreams that depend on it, and the Observations in those Datastreams, but not the Locations of the Thing, since Locations can exist without a relation to a Thing.

Requirement 32: Deleting Entitites

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/delete
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service that supports data modification SHALL support delete requests as described in section Clause 8.10.10.

8.10.11.  Deleting Entities by Filter

Sending individual delete requests for each entity to be deleted is very inefficient when many entities need to be deleted. For example for maintenance, when all Observations older than a certain date need to be deleted, a client would first have to sent a read request to find all entities older than the threshold data, and then sent a delete request for each of the returned entities. To make deleting a large number of entities more efficient, a server may implement filtered-delete capability.

When filtered-delete is supported, a client can send a delete request to an URI pattern that addresses an entity set (Clause 8.6.4 or Clause 8.6.9) with the $filter option (Clause 8.9.3.10). The server will delete all entities from the set that match the filter.

Requirement 33: Deleting Entities by Filter

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/api/cud/filtered_delete
Included inRequirements class 4: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/cud
Statement

A service advertising this requirements in its service document SHALL support the mass-deleting of entities as described in section Clause 8.10.11.

9.  HTTP Interface Bindings

9.1.  Introduction

The HTTP Bindings specify how access the SensorThings API using the HTTP protocol.

Requirements class 5: HTTP Interface Bindings

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req-class/binding/http
Obligationrequirement
Target typeInterface Binding
Conformance classConformance class A.1: http://www.opengis.net/spec/sensorthings/2.0/conf-class/binding/http
PrerequisiteRequirements class 1: http://www.opengis.net/spec/sensorthings/2.0/req-class/datamodel/core
Normative statementsRequirement 34: http://www.opengis.net/spec/sensorthings/2.0/req/binding/http/advertisement
Requirement 35: http://www.opengis.net/spec/sensorthings/2.0/req/binding/http/request_response

9.2.  HTTP Binding Advertisement

To help a client find the HTTP endpoints of a SensorThings service, the endpoints of the service are documented in the serverSettings object of the service documents of all request-response bindings, as described in Clause 8.9.2.2. If the service supports the HTTP interface binding, then the serverSettings object SHALL contain a attribute of type Object, with the name

http://www.opengis.net/spec/sensorthings/2.0/req/binding/http

This Object SHALL contain a attribute named endpoints of type Array. The JSON Array endpoints SHALL hold a list of URL Schemes that can be used to connect to the HTTP service

Requirement 34: Binding Advertisement

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/http/advertisement
Included inRequirements class 5: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/http
Statement

If a service implements any HTTP bindings, then the HTTP endpoints of the service SHALL be advertised in the service documents of all implemented request-response bindings, as described in Clause 9.2.

9.3.  Request / Response

The actions that can be executed on resources, as defined in the Clause 8 are mapped to HTTP Methods as defined in table Table 31.

Table 31 — Mapping of abstract request types to HTTP Methods.

Request typeHTTP Method
ReadGET
CreatePOST
UpdatePATCH
ReplacePUT
DeleteDELETE
ExecutePOST

Content for Create, Update, Replace or Execute requests is passed in the body of the HTTP request.

Request parameters (such as prefer, content-type and location) are passed as Headers.

HTTP HEAD and OPTIONS requests are treated as normal GET requests, but don’t return data. If a GET request with the same URL and headers would return an error, the HEAD or OPTION requests also returns this error.

Requirement 35: Request / Response

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/http/request_response
Included inRequirements class 5: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/http
PrerequisiteRequirements class 2: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/abstract
Statement

If a service advertises this requirement in the service document then the service SHALL map the request types as defined in the abstract API to HTTP methods as described in Clause 9.3.

10.  MQTT Interface Bindings

10.1.  Introduction

The MQTT Bindings specify how to access the SensorThings API using the MQTT 5.0 protocol (OASIS mqtt-v5.0). This binding consists of three parts that can be implemented independently: Clause 10.3, Clause 10.4 and Clause 10.5.

10.2.  MQTT Binding Advertisement

To help a client find the MQTT endpoints of a SensorThings service, the endpoints of the service are documented in the serverSettings object of the service documents of all request-response bindings, as described in Clause 8.9.2.2. If the service supports any MQTT interface bindings, then the serverSettings object SHALL contain a attribute of type Object, with the name

http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt

This Object SHALL contain a attribute named endpoints of type Array. The JSON Array endpoints SHALL hold a list of URL Schemes that can be used to connect to the MQTT service

Requirement 36: Binding Advertisement

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/advertisement
Included inRequirements class 6: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/mqtt
Statement

If a service implements any MQTT bindings, then the MQTT endpoints of the service SHALL be advertised in the service documents of all implemented request-response bindings, as described in Clause 10.2.

10.3.  Request / Response

MQTT 5.0 formalises a request-response pattern over the MQTT protocol (OASIS mqtt-v5.0, Section 4.10) that allows the use of the REST API over the MQTT protocol. See Figure 3 for a basic overview of the request-response pattern in MQTT 5.0.

MQTT 5.0 also defines User Properties (OASIS mqtt-v5.0, Section 3.3.2.3.7) that can be used to pass application-defined key-value pairs with a published message.

 

Figure 3 — MQTT 5 request-response pattern

Using the basic request-response pattern, and the User Properties of MQTT 5.0, the abstract API defined in Clause 8 can be implemented over the MQTT protocol.

  • Requests are sent to the topic v2.0/$request.

  • The URL, including query parameters, for the request is passed in the User Attribute named url (case-insensitive). The URL does not need to be URL-Encoded.

  • The request type (Clause 8.7) is passed in the User Property named type.

  • Request parameters (such as prefer, content-type and location) are passed as User Properties.

  • Content is sent as the payload of the message.

  • The request must contain a response topic that follows the Response Information passed by the broker.

  • The request may contain correlation data to help the client associate the response to the request.

  • all URLs pointing to the API start with the version of the API and contain no scheme, host or port.

To minimise the size of the returned payload, by default the json format is used with metadata=none (Clause 8.9.3.11.2).

EDITORIAL NOTE

Check if there really is no need to URL-Encode the url.

 

Topic: v2.0/$request
ResponseTopic: responses/userxyz
CorrelationData: 42
User Properties:
  url: v2.0
  type: read
  accept: */*
Payload: <empty>

Listing 75 — Message requesting the service document

 

Topic: responses/userxyz
CorrelationData: 42
User Properties:
  content-type: application/json;charset=UTF-8
Payload: <the service document>

Listing 76 — Response message to the previous read request

 

Topic: v2.0/$request
ResponseTopic: responses/userxyz
CorrelationData: 43
User Properties:
  url: v2.0/Things?$top=1&$orderby=id
  type: read
  accept: */*
Payload: <empty>

Listing 77 — Message requesting the first thing, ordered by id

 

Topic: responses/userxyz
CorrelationData: 43
User Properties:
  content-type: application/json;charset=UTF-8
Payload:
{
  "value": [
    {
      "id": 1,
      "name": "Oven",
      "description": "This thing is an oven.",
      "properties": {
        "owner": "Ulrike Schmidt",
        "color": "Black"
      }
    }
  ],
  "@nextLink": "v2.0/Things?$top=1&$skip=1&$orderby=id"
}

Listing 78 — Response message to the previous read request

 

Topic: v2.0/$request
ResponseTopic: responses/userxyz
User Properties:
  url: v2.0/Things
  type: create
  content-type: application/json
  accept: */*
Payload:
{
  "id": 1,
  "name": "Oven",
  "description": "This thing is an oven.",
  "properties": {
    "owner": "Ulrike Schmidt",
    "color": "Black"
  }
}

Listing 79 — Message creating a new thing

 

Topic: responses/userxyz
User Properties:
  content-type: application/json;charset=UTF-8
  location: v2.0/Things(1)
Payload: <empty>

Listing 80 — Response message to the previous create request

Requirement 37: Request / Response

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/request_response
Included inRequirements class 6: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/mqtt
PrerequisiteRequirements class 2: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/abstract
Statement

If a service advertises this requirement in the service document then the service SHALL implement the abstract API as described in Clause 10.3.

10.4.  Publish / Subscribe

10.4.1.  General

MQTT subscriptions are allowed on EntitySets (Clause 8.6.4, Clause 8.6.9), individual entities (Clause 8.6.5, Clause 8.6.8), and individual entity attributes (Clause 8.6.6, Clause 8.6.7).

To get all updates for an EntitySet or Entity, clients can subscribe to the topic that matches the plain URL pattern, without service root, and without a preceding slash (/).

When an entity or attribute is created, updated/replaced or deleted, that is relevant for the subscription, the service returns a complete JSON representation of the affected entity in the payload of the message.

The action that caused the notification is specified in the User Property named type, with a value of create, update or delete. Replace actions are published with the type update.

 

v2.0/Datastreams(4)/Observations

User Properties:
  type: create
Payload:
{
  "id": 123,
  "result": 45,
  "phenonmenonTime": "2015-02-05T17:00:00Z"
}

Listing 81 — Topic to use for receiving all updates for the Observations of a specific Datastream, and a typical message notifying about the creation of a new Observation

Since OData URLs are recursive, MQTT wildcards (# and +) are not allowed in subscriptions in the SensorThings topic tree.

Like HTTP URLs, MQTT topic in the SensorThings API can be extended with query options. Query options are separated from the topic with a question mark character ( ?) and separated using an ampersant (&). Query options are listed below.

Requirement 38: MQTT Publish / Subscribe

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub
Included inRequirements class 6: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/mqtt
Normative statementsRequirement 39: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/select
Requirement 40: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/expand
Requirement 41: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/filter
Statement

If a service advertises this requirement in the service document then the service SHALL implement the publish-subscribe API as described in Clause 10.4.

10.4.2.  $select

The $select query option (Clause 8.9.3.3) can be added to topics to reduce the amount of data that is sent.

 

v2.0/Datastreams(4)/Observations?$select=phenomenonTime,result

Listing 82 — Topic to use for receiving all updates for the Observations of a specific Datastream, limited to only the phenomenonTime and result attributes

Requirement 39: MQTT Publish / Subscribe Select

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/select
Statement

If a service advertises this requirement in the service document then the service SHALL implement support for the $select option as described in Clause 10.4.2.

10.4.3.  $expand

The $expand query option (Clause 8.9.3.5) can be added to topics to indicate that certain entities related to the created or updated entity should be sent. This can, for instance, be useful when dealing with moving sensors, to receive new Observations together with their ProximateFeatureOfInterest.

 

v2.0/Datastreams(4)/Observations?$expand=ProximateFeatureOfInterest

Listing 83 — Topic to use for receiving all updates for the Observations of a specific Datastream

Requirement 40: MQTT Publish / Subscribe Expand

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/expand
Statement

If a service advertises this requirement in the service document then the service SHALL implement support for the $expand option as described in Clause 10.4.3.

10.4.4.  $filter

The $filter query option (Clause 8.9.3.10) can be used to only receive notification of certain changes.

Requirement 41: MQTT Publish / Subscribe Filter

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/filter
Statement

If a service advertises this requirement in the service document then the service SHALL implement support for the $filter option as described in Clause 10.4.4.

10.5.  Simple Create

Since simple clients, like sensors, may not be capable of handling the full MQTT request/reponse pattern, the simple-create pattern allows for a simpler way to create entities. Entities can be created by sending a publish request to the topic of an EntitySet ( Clause 8.6.4, Clause 8.6.9), without service root, and without a preceding slash (/), followed by /create.

 

Topic: v2.0/Datastreams(4)/Observations/create
Payload:
{
  "result": 42,
  "phenomenonTime": {
    "start": "2017-11-12T13:00:00Z"
  }
}

Listing 84 — Publish message used to create an Observation in Datastream 4.

More advanced clients are adviced to use the MQTT Request/Response pattern to create entities, since it allows the server to return a success or failure response on entity creation.

Requirement 42: MQTT Simple Create

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/simple_create
Included inRequirements class 6: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/mqtt
Statement

If a service advertises this requirement in the service document then the service SHALL implement support simple entity creation as described in Clause 10.5.

11.  OGC API — Common Interface Bindings

11.1.  General

The OGC API — Common Bindings specify how to combine the SensorThings API with other OGC APIs.

12.  Media Types for any data encoding(s)

The SensorThings API references the following media types:

  • application/json

  • application/json-patch+json

  • application/geo+json

  • application/geopose+json

  • text/plain


Annex A
(informative)
Conformance Class Abstract Test Suite (Normative)

A.1.  Conformance Class A

Conformance class A.1

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf-class/binding/http
Requirements classRequirements class 5: http://www.opengis.net/spec/sensorthings/2.0/req-class/binding/http
PrerequisiteConformance class A.3: http://www.opengis.net/spec/sensorthings/2.0/conf-class/datamodel/core
Target TypeWeb API
Conformance testsAbstract test A.1: http://www.opengis.net/spec/sensorthings/2.0/conf/binding/http/advertisement
Abstract test A.2: http://www.opengis.net/spec/sensorthings/2.0/conf/binding/http/request_response

Abstract test A.1

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/http/advertisement
RequirementRequirement 34: http://www.opengis.net/spec/sensorthings/2.0/req/binding/http/advertisement
Test purpose

Validate the binding advertisement in the service document.

Test method

For each request_response binding:

  1. Construct a path for the service document.

  2. Issue a Read request on that path.

  3. Validate that the http binding is advertised, and endpoints are set.

Abstract test A.2

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/http/request_response
RequirementRequirement 35: http://www.opengis.net/spec/sensorthings/2.0/req/binding/http/request_response
PrerequisiteConformance class A.4: http://www.opengis.net/spec/sensorthings/2.0/conf-class/api/abstract
Test purpose

Validate that the resource paths advertised through the API conform with HTTP 1.1 and, where appropriate, TLS.

Test method
  1. All compliance tests SHALL be configured to use the HTTP 1.1 protocol exclusively.

  2. For APIs which support HTTPS, all compliance tests SHALL be configured to use HTTP over TLS (RFC 2818) with their HTTP 1.1 protocol.

A.2.  Conformance Class B

Abstract test A.3

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/advertisement
RequirementRequirement 36: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/advertisement
Test purpose

Validate the MQTT advertisement in the service documents of all request-response bindings.

Test method

For each request-response binding:

  1. Construct a path for the service document.

  2. Issue a Read request on that path.

  3. Validate that the mqtt binding is advertised, and endpoints are set.

Abstract test A.4

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/request_response
RequirementRequirement 37: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/request_response
PrerequisiteConformance class A.4: http://www.opengis.net/spec/sensorthings/2.0/conf-class/api/abstract
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.5

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/pub_sub
RequirementRequirement 38: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.6

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/pub_sub/select
RequirementRequirement 39: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/select
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.7

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/pub_sub/expand
RequirementRequirement 40: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/expand
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.8

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/pub_sub/filter
RequirementRequirement 41: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/pub_sub/filter
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.9

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/binding/mqtt/simple_create
RequirementRequirement 42: http://www.opengis.net/spec/sensorthings/2.0/req/binding/mqtt/simple_create
Test purpose

Validate that …​

Test method
  1. See if …​

A.3.  Conformance Class C

Abstract test A.10

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/thing
RequirementRequirement 1: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/thing
Test purpose

Validate that the API Definition document can be retrieved from the expected location.

Test method
  1. See if …​

Abstract test A.11

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/location
RequirementRequirement 2: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/location
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.12

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/historical-location
RequirementRequirement 3: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/historical-location
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.13

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/sensor
RequirementRequirement 5: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/sensor
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.14

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/datastream
RequirementRequirement 4: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/datastream
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.15

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/observed-property
RequirementRequirement 6: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/observed-property
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.16

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/feature
RequirementRequirement 8: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/feature
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.17

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/feature-type
RequirementRequirement 9: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/feature-type
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.18

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/observation
RequirementRequirement 7: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/observation
Test purpose

Validate that the EntityType has the required attributes and relations.

Test method
  1. See if …​

Abstract test A.19

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/datamodel/core/integrity
RequirementRequirement 10: http://www.opengis.net/spec/sensorthings/2.0/req/datamodel/core/integrity
Test purpose

Validate integrity is ensured.

Test method
  1. See if …​

A.4.  Conformance Class D

Conformance class A.4

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf-class/api/abstract
Requirements classRequirements class 2: http://www.opengis.net/spec/sensorthings/2.0/req-class/api/abstract
Conformance testsConformance class A.5: http://www.opengis.net/spec/sensorthings/2.0/conf-class/api/read
Conformance class A.6: http://www.opengis.net/spec/sensorthings/2.0/conf-class/api/cud

Abstract test A.20

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/paths
RequirementRequirement 11: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/paths
Test purpose

Validate that all the specified paths can be read, for the implemented data model.

Test method
  1. For each binding that supports request-response

  2. For each URL pattern defined in Clause 8.9.2 .

Abstract test A.21

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/precedence
RequirementRequirement 12: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/precedence
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.22

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/select
RequirementRequirement 13: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/select
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.23

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/select_distinct
RequirementRequirement 14: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/select_distinct
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.24

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/expand
RequirementRequirement 15: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/expand
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.25

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/top
RequirementRequirement 16: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/top
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.26

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/skip
RequirementRequirement 17: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/skip
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.27

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/count
RequirementRequirement 18: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/count
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.28

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/orderby
RequirementRequirement 19: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/orderby
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.29

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/filter
RequirementRequirement 20: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/filter
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.30

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/format
RequirementRequirement 21: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/format
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.31

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/read/options/pagination
RequirementRequirement 22: http://www.opengis.net/spec/sensorthings/2.0/req/api/read/options/pagination
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.32

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/advertisement
RequirementRequirement 23: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/advertisement
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.33

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/create
RequirementRequirement 24: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/create
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.34

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/deep_insert
RequirementRequirement 25: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/deep_insert
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.35

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/update
RequirementRequirement 26: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/update
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.36

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/replace
RequirementRequirement 27: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/replace
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.37

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/deep_update
RequirementRequirement 28: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/deep_update
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.38

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/json_patch
RequirementRequirement 29: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/json_patch
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.39

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/return_value
RequirementRequirement 30: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/return_value
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.40

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/update_relations
RequirementRequirement 31: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/update_relations
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.41

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/delete
RequirementRequirement 32: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/delete
Test purpose

Validate that …​

Test method
  1. See if …​

Abstract test A.42

Identifierhttp://www.opengis.net/spec/sensorthings/2.0/conf/api/cud/filtered_delete
RequirementRequirement 33: http://www.opengis.net/spec/sensorthings/2.0/req/api/cud/filtered_delete
Test purpose

Validate that …​

Test method
  1. See if …​


Annex B
(informative)
Short CSDL example with comments

 

{
   
"$Version": "4.01",  // OData version
   
"$EntityContainer": "org.OGC.SensorThingsV2",  // Namespace + . + container name
   
"org.OGC": {         // Namespace
       
"Datastream": {  // EntityType name
           
"$Kind": "EntityType",  // Object is an EntityType
           
"$Key": [    // Primary key of the EntityType
               
"id"     // Primary key consists of the id field
           
],
           
"id": {                   // id field, structural properties have no $Kind
               
"$Type": "Edm.Int64"  // Type of the id field
           
},                        // Not nullable, but PrimaryKeys are auto generated
           
"name": {},   // name field, Default $Type=Edm.String, not nullable
           
"properties": {                 // Property properties
               
"$Type": "org.OGC.Object",  // custom type defined in org.OGC namespace
               
"$Nullable": true           // Nullable, thus Optional
           
},
           
"phenomenonTime": {               // Property phenomenonTime
               
"$Type": "org.OGC.TM_Period", // custom type defined in org.OGC namespace
               
"$Nullable": true             // Nullable, thus Optional
           
},
           
"Observations": {                   // Property Observations
               
"$Kind": "NavigationProperty",  // NavigationProperty
               
"$Collection": true,            // links to a Set of Entities
               
"$Partner": "Datastream",       // inverse link is called Datastream
               
"$Type": "org.OGC.Observation", // Target is of type Observation
               
"$Nullable": true               // can be an empty set
           
}
       
},
       
"Observation": {            // EntityType name
           
"$Kind": "EntityType",  // Object is an EntityType
           
"$Key": [               // Primary key of the EntityType
               
"id"                // Primary key consists of the id field
           
],
           
"id": {                   // id field, structural properties have no $Kind
               
"$Type": "Edm.Int64"  // Type of the id field
           
},                        // Not nullable, but PrimaryKeys are auto generated
           
"result": {
               
"$Type": "Edm.Untyped"  // Untyped=can be anything
           
},
           
"Datastream": {                    // Property Datastream linking to a single Entity
               
"$Kind": "NavigationProperty", // is a NavigationProperty
               
"$Partner": "Observations",    // inverse relation is called Observations
               
"$Type": "org.OGC.Datastream"  //  links to a Datastream
           
}                                  // No $Nullable, thus mandatory!
       
},
       
"Object": {                 // Custom type Object
           
"$Kind": "ComplexType", // is a complex type
           
"$OpenType": true       // Open, thus can hold user-defined properties
       
},
       
"TM_Period": {                         // Custom type TM_Period
           
"$Kind": "ComplexType",            // is a complex type
           
"start": {                         // Has a structural property named start
               
"$Type": "Edm.DateTimeOffset"  // that is of type DataTimeOffset
           
},                                 // No $Nullable, thus mandatory!
           
"end": {                           // Has a structural property named end
               
"$Type": "Edm.DateTimeOffset"  // that is of type DataTimeOffset
           
}
       
},
       
"SensorThingsV2": {             // The entity container defining the base entity sets
           
"$Kind": "EntityContainer",
           
"Datastreams": {                     // The v2.0/Datastreams entitySet
               
"$Collection": true,             // is an entity set
               
"$Type": "org.OGC.Datastream",   // containing Datastreams
               
"$NavigationPropertyBinding": {  // The navigationProperties link to other top-level sets
                   
"Observations": "Observations"  // v2.0/Datastreams(x)/Observations are also in v2.0/Observations
               
}
           
},
           
"Observations": {                    // The v2.0/Observations entitySet
               
"$Collection": true,             // is an entity set
               
"$Type": "org.OGC.Observation",  // containing Observations
               
"$NavigationPropertyBinding": {
                   
"Datastream": "Datastreams"  // v2.0/Observations(x)/Datastream is also in v2.0/Datastreams
               
}
           
}
       
}
   
}
}

Listing B.1 — A shortened example CSDL definition with only (incomplete) Datastreams and Observations.


Annex C
(informative)
Example SensorThings API Core CSDL

 

{
   
"$Version": "4.01",
   
"$EntityContainer": "org.OGC.SensorThingsV2",
   
"org.OGC": {
       
"Datastream": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"resultType": {
               
"$Type": "org.OGC.Object"
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"observedArea": {
               
"$Type": "Edm.Geometry",
               
"$Nullable": true
           
},
           
"phenomenonTime": {
               
"$Type": "org.OGC.TM_Period",
               
"$Nullable": true
           
},
           
"resultTime": {
               
"$Type": "org.OGC.TM_Period",
               
"$Nullable": true
           
},
           
"Observations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Datastream",
               
"$Type": "org.OGC.Observation",
               
"$Nullable": true
           
},
           
"ObservedProperties": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Datastreams",
               
"$Type": "org.OGC.ObservedProperty",
               
"$Nullable": true
           
},
           
"Sensor": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "Datastreams",
               
"$Type": "org.OGC.Sensor"
           
},
           
"Thing": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "Datastreams",
               
"$Type": "org.OGC.Thing"
           
},
           
"ultimateFeatureOfInterest": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "Datastreams",
               
"$Type": "org.OGC.Feature",
               
"$Nullable": true
           
}
       
},
       
"Feature": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"encodingType": {
               
"$Nullable": true
           
},
           
"feature": {
               
"$Type": "org.OGC.Geometry",
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"Datastreams": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "ultimateFeatureOfInterest",
               
"$Type": "org.OGC.Datastream",
               
"$Nullable": true
           
},
           
"FeatureTypes": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Features",
               
"$Type": "org.OGC.FeatureType",
               
"$Nullable": true
           
},
           
"Observations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "proximateFeatureOfInterest",
               
"$Type": "org.OGC.Observation",
               
"$Nullable": true
           
}
       
},
       
"FeatureType": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"definition": {
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"Features": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "FeatureTypes",
               
"$Type": "org.OGC.Feature",
               
"$Nullable": true
           
}
       
},
       
"HistoricalLocation": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"time": {
               
"$Type": "Edm.DateTimeOffset"
           
},
           
"Locations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "HistoricalLocations",
               
"$Type": "org.OGC.Location",
               
"$Nullable": true
           
},
           
"Thing": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "HistoricalLocations",
               
"$Type": "org.OGC.Thing"
           
}
       
},
       
"Location": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"encodingType": {
               
"$Nullable": true
           
},
           
"location": {
               
"$Type": "org.OGC.Geometry",
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"HistoricalLocations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Locations",
               
"$Type": "org.OGC.HistoricalLocation",
               
"$Nullable": true
           
},
           
"Things": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Locations",
               
"$Type": "org.OGC.Thing",
               
"$Nullable": true
           
}
       
},
       
"Observation": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"phenomenonTime": {
               
"$Type": "org.OGC.TM_Object",
               
"$Nullable": true
           
},
           
"resultTime": {
               
"$Type": "Edm.DateTimeOffset",
               
"$Nullable": true
           
},
           
"validTime": {
               
"$Type": "org.OGC.TM_Period",
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"result": {
               
"$Type": "Edm.Untyped",
               
"$Nullable": true
           
},
           
"Datastream": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "Observations",
               
"$Type": "org.OGC.Datastream"
           
},
           
"proximateFeatureOfInterest": {
               
"$Kind": "NavigationProperty",
               
"$Partner": "Observations",
               
"$Type": "org.OGC.Feature",
               
"$Nullable": true
           
}
       
},
       
"ObservedProperty": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"definition": {},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"Datastreams": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "ObservedProperties",
               
"$Type": "org.OGC.Datastream",
               
"$Nullable": true
           
}
       
},
       
"Sensor": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"encodingType": {
               
"$Nullable": true
           
},
           
"metadata": {
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"Datastreams": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Sensor",
               
"$Type": "org.OGC.Datastream",
               
"$Nullable": true
           
}
       
},
       
"Thing": {
           
"$Kind": "EntityType",
           
"$Key": [
               
"id"
           
],
           
"id": {
               
"$Type": "Edm.Int64"
           
},
           
"name": {},
           
"description": {
               
"$Nullable": true
           
},
           
"properties": {
               
"$Type": "org.OGC.Object",
               
"$Nullable": true
           
},
           
"Datastreams": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Thing",
               
"$Type": "org.OGC.Datastream",
               
"$Nullable": true
           
},
           
"HistoricalLocations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Thing",
               
"$Type": "org.OGC.HistoricalLocation",
               
"$Nullable": true
           
},
           
"Locations": {
               
"$Kind": "NavigationProperty",
               
"$Collection": true,
               
"$Partner": "Things",
               
"$Type": "org.OGC.Location",
               
"$Nullable": true
           
}
       
},
       
"Geometry": {
           
"$Kind": "TypeDefinition",
           
"$UnderlyingType": "Edm.Geometry",
           
"@Core.Description": "A Free Location object"
       
},
       
"Object": {
           
"$Kind": "ComplexType",
           
"$OpenType": true,
           
"@Core.Description": "A free object that can contain anything"
       
},
       
"TM_Object": {
           
"$Kind": "ComplexType",
           
"@Core.Description": "An ISO time instant or time interval.",
           
"start": {
               
"$Type": "Edm.DateTimeOffset"
           
},
           
"end": {
               
"$Type": "Edm.DateTimeOffset",
               
"$Nullable": true
           
}
       
},
       
"TM_Period": {
           
"$Kind": "ComplexType",
           
"@Core.Description": "An ISO time interval.",
           
"start": {
               
"$Type": "Edm.DateTimeOffset"
           
},
           
"end": {
               
"$Type": "Edm.DateTimeOffset"
           
}
       
},
       
"SensorThingsV2": {
           
"$Kind": "EntityContainer",
           
"Datastreams": {
               
"$Collection": true,
               
"$Type": "org.OGC.Datastream",
               
"$NavigationPropertyBinding": {
                   
"ultimateFeatureOfInterest": "Features",
                   
"Observations": "Observations",
                   
"ObservedProperties": "ObservedProperties",
                   
"Thing": "Things",
                   
"Sensor": "Sensors"
               
}
           
},
           
"Features": {
               
"$Collection": true,
               
"$Type": "org.OGC.Feature",
               
"$NavigationPropertyBinding": {
                   
"Datastreams": "Datastreams",
                   
"FeatureTypes": "FeatureTypes",
                   
"Observations": "Observations"
               
}
           
},
           
"FeatureTypes": {
               
"$Collection": true,
               
"$Type": "org.OGC.FeatureType",
               
"$NavigationPropertyBinding": {
                   
"Features": "Features"
               
}
           
},
           
"HistoricalLocations": {
               
"$Collection": true,
               
"$Type": "org.OGC.HistoricalLocation",
               
"$NavigationPropertyBinding": {
                   
"Locations": "Locations",
                   
"Thing": "Things"
               
}
           
},
           
"Locations": {
               
"$Collection": true,
               
"$Type": "org.OGC.Location",
               
"$NavigationPropertyBinding": {
                   
"Things": "Things",
                   
"HistoricalLocations": "HistoricalLocations"
               
}
           
},
           
"Observations": {
               
"$Collection": true,
               
"$Type": "org.OGC.Observation",
               
"$NavigationPropertyBinding": {
                   
"Datastream": "Datastreams",
                   
"proximateFeatureOfInterest": "Features"
               
}
           
},
           
"ObservedProperties": {
               
"$Collection": true,
               
"$Type": "org.OGC.ObservedProperty",
               
"$NavigationPropertyBinding": {
                   
"Datastreams": "Datastreams"
               
}
           
},
           
"Sensors": {
               
"$Collection": true,
               
"$Type": "org.OGC.Sensor",
               
"$NavigationPropertyBinding": {
                   
"Datastreams": "Datastreams"
               
}
           
},
           
"Things": {
               
"$Collection": true,
               
"$Type": "org.OGC.Thing",
               
"$NavigationPropertyBinding": {
                   
"Datastreams": "Datastreams",
                   
"Locations": "Locations",
                   
"HistoricalLocations": "HistoricalLocations"
               
}
           
}
       
}
   
}
}

Listing C.1 — A CSDL example for the SensorThings API Core


Annex D
(informative)
Revision History

Table D.1 — Revision History

DateReleaseEditorPrimary clauses modifiedDescription
2023-05-090.1Hylke van der Schaafallinitial version

Bibliography

[1]  ITU-T Y.2060: Overview of the Internet of Things, 2012. Available Online: https://www.itu.int/rec/t-rec-y.2060-201206-i