Use FROST-Server with DeltaTwin®
Empowering DeltaTwin® users with FROST-Server capabilities requires two steps :
- activating the relevant plugins
- articulating and explaining concepts shared by DeltaTwin® and FROST-Server.
FROST-Server activated plugins
- GeoJSON ResultFormat for a seamless visualization, since DeltaTwin® natively offers an interactive visualization of GeoJSON
- Projects Data Model Plugin for securing and organizing the access to STA entities by associating FROST-Server User et UserProjectRole to DeltaTwin® users and tenancies
- OData
- BatchProcessing
STA endpoints in DeltaTwin® API
Each request goes through the DeltaTwin® API, exposing the exact endpoints described in the STA standard and the “Project” plugin of the FROST-Server implementation.
DeltaTwin® users are given read-only access to a public project deltatwin-sensor-data which contains data selected and homogenized by the Deltatwin team.
FROST-Server in action
To better understand the utility of FROST-Server, and how its integration in DeltaTwin® is a MIM7 enabler for the users, we will now examine a scenario illustrating the real-world application of SensorThings API concepts.
Let’s take “Identification of flooded land parcels on the border between two countries” as an illustrative use case. In the context of data interoperability across different domains and data providers, this use case focuses on identifying flooded parcels along the Rhine River (which forms a natural border between multiple countries). To achieve this, we must integrate heterogeneous hydrological data from measurement stations in 🇫🇷 France , 🇩🇪 Germany , 🇳🇱 Netherlands , and 🇨🇭 Switzerland , each of which may use distinct formats, standards and representations for river flow and level measurements. DeltaTwin® addresses the challenge, allowing its users to have a unified “sink” for their sensor data, exposed as a SensorThings API.
At this stage of development, we are providing a preliminary integration that includes providing the FROST-Server instance and setting up the user projects. However, users must independently develop the DeltaTwin® components required to convert their input data sources into STA entities.
We recognize this complexity and, as a planned next step in our roadmap, will introduce a visual drag-and-drop workflow editor to simplify the task of mapping data attributes for users.
Mapping Hub’Eau entities to STA
We will focus on ingesting Hub’Eau API (called “Hydrométrie”) data into the FROST-Server instance. We have identified the following endpoints:
GET https://hubeau.eaufrance.fr/api/v2/hydrometrie/observations_tr: List hydrometric observationsGET https://hubeau.eaufrance.fr/api/v2/hydrometrie/referentiel/sites: List hydrometric sitesGET https://hubeau.eaufrance.fr/api/v2/hydrometrie/referentiel/stations: List hydrometric stations
Here is a sample output of each endpoint:
Hub’Eau observations
{
"count": 40322612,
"first": "https://hubeau.eaufrance.fr/api/v2/hydrometrie/observations_tr?sort=desc&cursor=&size=20",
"prev": null,
"next": "https://hubeau.eaufrance.fr/api/v2/hydrometrie/observations_tr?sort=desc&cursor=AoJwmp2a7ZoDPwpQMjM4MDAxMF9QMjM4MDAxMDAxX0hfMjAyNS0xMi0wMVQxNDo1NTowMA%3D%3D&size=20",
"api_version": "2.0.1",
"data": [
{
"code_site": "O9570001",
"code_station": "O957000101",
"grandeur_hydro": "H",
"date_debut_serie": "2025-12-01T07:00:00Z",
"date_fin_serie": "2025-12-01T14:55:00Z",
"code_systeme_alti_serie": 31,
"date_obs": "2025-12-01T14:55:00Z",
"resultat_obs": 1000,
"code_methode_obs": 0,
"libelle_methode_obs": "Mesurée",
"code_qualification_obs": 16,
"libelle_qualification_obs": "Non qualifiée",
"longitude": -0.365956846,
"latitude": 44.454086406,
"code_statut": 4,
"libelle_statut": "Brute",
"code_continuite": 0,
"libelle_continuite": "Continue"
},
...
]
}After examining the content of the outputs, we identified the following mappings to STA entites:
- STA Location → Hub’Eau Site
id→code_sitename→libelle_sitedescription→libelle_site(there is no attribute providing a description of the Hub’Eau site)encodingType→"application/json"location→geometryproperties→ this will contains all the remaining attributes of the Hub’Eau site
- STA Thing → Hub’Eau Station
id→code_stationname→libelle_stationdescription→libelle_station(there is no attribute providing a description of the Hub’Eau station)Locations→code_site(a station always belong the same site)properties→ this will contain all the remaining attributes of the Hub’Eau station
- STA Observation → Hub’Eau Observation
id(auto-generated)phenomenonTime→date_obsresultTime→date_obs(Hub’Eau doesn’t differentiate between between the instant the observation happens and instant it was generated or made available)result→resultat_obs
- STA ObservedProperty : After noticing that the attribute
grandeur_hydrohave eitherHorQvalues, we decide to add twoObservedPropertyinstances (STA_OBSERVED_PROPERTIES ) - STA Sensor : Hub’Eau doesn’t provide any description of the instruments used for measuring the observation. We decided to create a generic STA Sensor for each ObservedProperty (STA_SENSOR )
- STA FeatureOfInterest : For simplicity, we consider only one FeatureOfInterest, i.e. the Rhine river (STA_FEATURE_OF_INTEREST )
- STA Datasteam → Hub’Eau Station : We associate one
HDatastream and oneQDatastream to each Hub’Eau station-
id→code_station+“H”/“Q” -
name→River Water "H"/"Q" at Station code_station -
observationType→”https://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement” -
unitOfMeasurement→-
"unitOfMeasurement": { "name": "cubic metre per second (Q)", "symbol": "m³/s", "definition": "A unit of volumetric flow rate expressing the volume of water passing a point in a river per second." } -
"unitOfMeasurement": { "name": "meter (H)", "symbol": "m", "definition": "A unit of length representing the height of the water surface relative to a reference point or datum." }
-
-
observedArea,phenomenonTime,properties,resultTime→ non required attributes.
-
More implementation details about the mappings are available in this DeltaTwin® component : MIM-Rhin

Querying Hub’Eau data on a FROST-Server
After transforming heterogeneous data sources to their corresponding STA entities, we can now query the FROST-Server instance using DeltaTwin® dedicated endpoints that provide full route compatibility with the SensorThings API specification. For the following steps, we suppose that the FROST-Server endpoint is at https://api.deltatwin.gael.fr/sensorthings/, this URL might change (depending on the version of DeltaTwin® API).
For example, we can simply query the list of Things to get all measuring stations stored on the server :
curl --location 'https://api.deltatwin.gael.fr/sensorthings/Projects('\''deltatwin-sensor-data'\'')/Things' \
--header 'Authorization: Bearer XXXX'
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Things('0309cd61-90c9-470e-99d4-2ee4fb2c5f84')",
"@iot.id": "0309cd61-90c9-470e-99d4-2ee4fb2c5f84",
"name": "BINGEN",
"description": "BINGEN",
"properties": {
"agency": "STANDORT BINGEN",
"km": 528.36,
"latitude": 49.97034213591973,
"longitude": 7.899667963397104,
"longname": "BINGEN",
"number": "25300200",
"shortname": "BINGEN",
"uuid": "0309cd61-90c9-470e-99d4-2ee4fb2c5f84",
"water": {
"longname": "RHEIN",
"shortname": "RHEIN"
}
},
"restricted": false,
},
... the rest of the things
]
}We can query a specific Thing :
curl --location 'https://api.deltatwin.gael.fr/sensorthings/Projects('\''deltatwin-sensor-data'\'')/Things('\''U241202001'\'')' \
--header 'Authorization: Bearer XXXXX'
{
"@iot.id": "U241202001",
"name": "Le canal du Rhône au Rhin [Le Doubs] à Branne",
"description": "Le canal du Rhône au Rhin [Le Doubs] à Branne",
"properties": {
"altitude_ref_alti_station": 269000.0,
"code_commune_station": "25087",
"code_cours_eau": "----0022",
"code_departement": "25",
"code_finalite_station": "1 2",
"code_projection": 26,
"code_regime_station": 1,
"code_region": "27",
"code_sandre_reseau_station": [
"600000184"
],
"code_site": "U2412020",
"code_systeme_alti_site": 2,
"coordonnee_x_station": 960946.0,
"coordonnee_y_station": 6702831.0,
"date_activation_ref_alti_station": "2013-11-18T00:00:00Z",
"date_debut_ref_alti_station": "1969-10-27T00:00:00Z",
"date_fermeture_station": "1987-01-20T00:00:00Z",
"date_maj_ref_alti_station": "2013-11-18T00:00:00Z",
"date_maj_station": "2021-05-12T00:00:00Z",
"date_ouverture_station": "1969-10-27T00:00:00Z",
"en_service": false,
"influence_locale_station": 1,
"latitude_station": 47.374367098,
"libelle_commune": "BRANNE",
"libelle_cours_eau": "Canal du Rhône au Rhin",
"libelle_departement": "DOUBS",
"libelle_region": "BOURGOGNE-FRANCHE-COMTE",
"libelle_station": "Le canal du Rhône au Rhin [Le Doubs] à Branne",
"longitude_station": 6.459182682,
"qualification_donnees_station": 20,
"type_contexte_loi_stat_station": 1,
"type_loi_station": 2,
"type_station": "STD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/----0022"
}
}To “navigate” to the Datastreams associated with a specific Thing :
curl --location 'https://api.deltatwin.gael.fr/sensorthings/Projects('\''deltatwin-sensor-data'\'')/Things('\''U241202001'\'')/Datastreams' \
--header 'Authorization: Bearer XXXX'For additional information about how to navigate and manipulate SensorThings
API entities (using many OData-like keywords such as $count, $expand,
$select, $filter, $orderby, …), please consult the official
documentation .
Let’s examine a more advanced way to query entities, and progressively build a requests that will output, in GeoJson format, the latest observation related to observed-property-H of each thing. For this request we need a mix of path navigation and query keywords and operators.
Start with getting the ObservedProperty
GET https://api.deltatwin.gael.fr/sensorthings/ObservedProperties('observed-property-H')
{
"@iot.selfLink": "http://frost-server/v1.1/ObservedProperties('observed-property-H')",
"@iot.id": "observed-property-H",
"name": "River Water Level",
"definition": "https://qudt.org/vocab/quantitykind/Height",
"description": "The height of the water surface in the river relative to a reference point",
"Datastreams@iot.navigationLink": "http://frost-server/v1.1/ObservedProperties('observed-property-H')/Datastreams",
"MultiDatastreams@iot.navigationLink": "http://frost-server/v1.1/ObservedProperties('observed-property-H')/MultiDatastreams"
}Navigate to Datastreams
From an ObservedProperty we can only navigate to its Datastream :
GET https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')",
"@iot.id": "005124b2-ce9e-11f0-a1c9-83ad9e1e00e1",
"name": "",
"description": "",
"observationType": "",
"unitOfMeasurement": {
"name": null,
"symbol": null,
"definition": null
},
"phenomenonTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"restricted": false,
"ObservedProperty@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/ObservedProperty",
"Sensor@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Sensor",
"Thing@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Thing",
"Observations@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations"
},
...
]
}$expand the associated Thing
For each Datastream (associated to observed-property-H), we can $expand the thing associated to it :
GET https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams?$expand=Thing
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')",
"@iot.id": "005124b2-ce9e-11f0-a1c9-83ad9e1e00e1",
"name": "",
"description": "",
"observationType": "",
"unitOfMeasurement": {
"name": null,
"symbol": null,
"definition": null
},
"phenomenonTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"restricted": false,
"Thing": {
"@iot.selfLink": "http://frost-server/v1.1/Things('A021005050')",
"@iot.id": "A021005050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"properties": {
"code_commune_station": "99140",
"code_cours_eau": "A---0000",
"code_projection": 26,
"code_regime_station": 1,
"code_sandre_reseau_station": [
"POH001",
"POH044",
"POH905",
"RIC013",
"RIC062",
"RIC112",
"RIC262",
"RIC312"
],
"code_site": "A0210050",
"coordonnee_x_station": 1046200.0,
"coordonnee_y_station": 6727500.0,
"date_maj_station": "2025-10-10T00:00:00Z",
"date_ouverture_station": "1899-12-31T00:00:00Z",
"en_service": true,
"latitude_station": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"libelle_station": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"longitude_station": 7.606153158,
"qualification_donnees_station": 16,
"type_contexte_loi_stat_station": 1,
"type_loi_station": 0,
"type_station": "STD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false
},
"ObservedProperty@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/ObservedProperty",
"Sensor@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Sensor",
"Thing@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Thing",
"Observations@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations"
},
]
}$expand the Locations
For now, we have all the Datastream (associated with observed-property-H), and their info and their associated Thing. We can now $expand the Locations association to the Thing. We need the Location because it is the STA entity that holds the geometry data (needed to output a GeoJSON) :
GET https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams?$expand=Thing($expand=Locations)
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')",
"@iot.id": "005124b2-ce9e-11f0-a1c9-83ad9e1e00e1",
"name": "",
"description": "",
"observationType": "",
"unitOfMeasurement": {
"name": null,
"symbol": null,
"definition": null
},
"phenomenonTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"restricted": false,
"Thing": {
"@iot.selfLink": "http://frost-server/v1.1/Things('A021005050')",
"@iot.id": "A021005050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"properties": {
"code_commune_station": "99140",
"code_cours_eau": "A---0000",
"code_projection": 26,
"code_regime_station": 1,
"code_sandre_reseau_station": [
"POH001",
"POH044",
"POH905",
"RIC013",
"RIC062",
"RIC112",
"RIC262",
"RIC312"
],
"code_site": "A0210050",
"coordonnee_x_station": 1046200.0,
"coordonnee_y_station": 6727500.0,
"date_maj_station": "2025-10-10T00:00:00Z",
"date_ouverture_station": "1899-12-31T00:00:00Z",
"en_service": true,
"latitude_station": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"libelle_station": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"longitude_station": 7.606153158,
"qualification_donnees_station": 16,
"type_contexte_loi_stat_station": 1,
"type_loi_station": 0,
"type_station": "STD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false,
"Locations": [
{
"@iot.selfLink": "http://frost-server/v1.1/Locations('A0210050')",
"@iot.id": "A0210050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"encodingType": "application/json",
"location": {
"type": "Point",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"coordinates": [
7.6061531576193415,
47.55696990748868
]
},
"properties": {
"altitude_site": 246.0,
"code_commune_site": [
"99140"
],
"code_cours_eau": "A---0000",
"code_entite_hydro_site": "A---0000",
"code_projection": 26,
"code_systeme_alti_site": 0,
"code_troncon_hydro_site": "A0210000",
"code_zone_hydro_site": "A021",
"coordonnee_x_site": 1046200.0,
"coordonnee_y_site": 6727500.0,
"date_maj_site": "2024-03-19T00:00:00Z",
"grandeur_hydro": "Q",
"influence_generale_site": 2,
"latitude_site": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"longitude_site": 7.606153158,
"premier_mois_annee_hydro_site": 1,
"premier_mois_etiage_site": 1,
"statut_site": 1,
"surface_bv": 35878.0,
"type_contexte_loi_stat_site": [
1
],
"type_loi_site": [
0
],
"type_site": "STANDARD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false
}
]
},
"ObservedProperty@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/ObservedProperty",
"Sensor@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Sensor",
"Thing@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Thing",
"Observations@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations"
},
]
}Include the Observations in the request
After including geospatial attribute, now we can move to include the Observations in the request :
GET https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams?$expand=Thing($expand=Locations),Observations
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')",
"@iot.id": "005124b2-ce9e-11f0-a1c9-83ad9e1e00e1",
"name": "",
"description": "",
"observationType": "",
"unitOfMeasurement": {
"name": null,
"symbol": null,
"definition": null
},
"phenomenonTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"restricted": false,
"Thing": {
"@iot.selfLink": "http://frost-server/v1.1/Things('A021005050')",
"@iot.id": "A021005050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"properties": {
"code_commune_station": "99140",
"code_cours_eau": "A---0000",
"code_projection": 26,
"code_regime_station": 1,
"code_sandre_reseau_station": [
"POH001",
"POH044",
"POH905",
"RIC013",
"RIC062",
"RIC112",
"RIC262",
"RIC312"
],
"code_site": "A0210050",
"coordonnee_x_station": 1046200.0,
"coordonnee_y_station": 6727500.0,
"date_maj_station": "2025-10-10T00:00:00Z",
"date_ouverture_station": "1899-12-31T00:00:00Z",
"en_service": true,
"latitude_station": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"libelle_station": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"longitude_station": 7.606153158,
"qualification_donnees_station": 16,
"type_contexte_loi_stat_station": 1,
"type_loi_station": 0,
"type_station": "STD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false,
"Locations": [
{
"@iot.selfLink": "http://frost-server/v1.1/Locations('A0210050')",
"@iot.id": "A0210050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"encodingType": "application/json",
"location": {
"type": "Point",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"coordinates": [
7.6061531576193415,
47.55696990748868
]
},
"properties": {
"altitude_site": 246.0,
"code_commune_site": [
"99140"
],
"code_cours_eau": "A---0000",
"code_entite_hydro_site": "A---0000",
"code_projection": 26,
"code_systeme_alti_site": 0,
"code_troncon_hydro_site": "A0210000",
"code_zone_hydro_site": "A021",
"coordonnee_x_site": 1046200.0,
"coordonnee_y_site": 6727500.0,
"date_maj_site": "2024-03-19T00:00:00Z",
"grandeur_hydro": "Q",
"influence_generale_site": 2,
"latitude_site": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"longitude_site": 7.606153158,
"premier_mois_annee_hydro_site": 1,
"premier_mois_etiage_site": 1,
"statut_site": 1,
"surface_bv": 35878.0,
"type_contexte_loi_stat_site": [
1
],
"type_loi_site": [
0
],
"type_site": "STANDARD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false
}
]
},
"Observations": [
{
"@iot.selfLink": "http://frost-server/v1.1/Observations('00609a8c-ce9e-11f0-a1c9-ff0e0640ba52')",
"@iot.id": "00609a8c-ce9e-11f0-a1c9-ff0e0640ba52",
"phenomenonTime": "2025-12-01T00:00:00Z",
"resultTime": "2025-12-01T00:00:00Z",
"result": 5800.0,
"parameters": {
"code_continuite": 0,
"code_methode_obs": 0,
"code_qualification_obs": 16,
"code_site": "A0210050",
"code_station": "A021005050",
"code_statut": 4,
"code_systeme_alti_serie": 31,
"date_debut_serie": "2025-11-30T23:15:01Z",
"date_fin_serie": "2025-12-01T00:00:00Z",
"grandeur_hydro": "H",
"latitude": 47.556969907,
"libelle_continuite": "Continue",
"libelle_methode_obs": "Mesurée",
"libelle_qualification_obs": "Non qualifiée",
"libelle_statut": "Brute",
"longitude": 7.606153158
}
}
],
"Observations@iot.nextLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations?$top=1&$skip=1&$orderby=phenomenonTime+asc,%40iot.id+asc&$skipFilter=%28phenomenonTime+gt+2025-12-01T00%3A00%3A00Z%29",
"ObservedProperty@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/ObservedProperty",
"Sensor@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Sensor",
"Thing@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Thing",
"Observations@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations"
},
]
}Get the latest Observation
We need to $orderBy=phenomenonTime desc to sort Observations, and $top=1 :
GET https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams?$expand=Thing($expand=Locations),Observations($orderby=phenomenonTime desc;$top=1)
{
"value": [
{
"@iot.selfLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')",
"@iot.id": "005124b2-ce9e-11f0-a1c9-83ad9e1e00e1",
"name": "",
"description": "",
"observationType": "",
"unitOfMeasurement": {
"name": null,
"symbol": null,
"definition": null
},
"phenomenonTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T00:00:00Z/2025-12-01T09:00:00Z",
"restricted": false,
"Thing": {
"@iot.selfLink": "http://frost-server/v1.1/Things('A021005050')",
"@iot.id": "A021005050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"properties": {
"code_commune_station": "99140",
"code_cours_eau": "A---0000",
"code_projection": 26,
"code_regime_station": 1,
"code_sandre_reseau_station": [
"POH001",
"POH044",
"POH905",
"RIC013",
"RIC062",
"RIC112",
"RIC262",
"RIC312"
],
"code_site": "A0210050",
"coordonnee_x_station": 1046200.0,
"coordonnee_y_station": 6727500.0,
"date_maj_station": "2025-10-10T00:00:00Z",
"date_ouverture_station": "1899-12-31T00:00:00Z",
"en_service": true,
"latitude_station": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"libelle_station": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"longitude_station": 7.606153158,
"qualification_donnees_station": 16,
"type_contexte_loi_stat_station": 1,
"type_loi_station": 0,
"type_station": "STD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false,
"Locations": [
{
"@iot.selfLink": "http://frost-server/v1.1/Locations('A0210050')",
"@iot.id": "A0210050",
"name": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"description": "Le Rhin en Suisse [Bâle (Rheinhalle)]",
"encodingType": "application/json",
"location": {
"type": "Point",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"coordinates": [
7.6061531576193415,
47.55696990748868
]
},
"properties": {
"altitude_site": 246.0,
"code_commune_site": [
"99140"
],
"code_cours_eau": "A---0000",
"code_entite_hydro_site": "A---0000",
"code_projection": 26,
"code_systeme_alti_site": 0,
"code_troncon_hydro_site": "A0210000",
"code_zone_hydro_site": "A021",
"coordonnee_x_site": 1046200.0,
"coordonnee_y_site": 6727500.0,
"date_maj_site": "2024-03-19T00:00:00Z",
"grandeur_hydro": "Q",
"influence_generale_site": 2,
"latitude_site": 47.556969907,
"libelle_cours_eau": "Le Rhin",
"longitude_site": 7.606153158,
"premier_mois_annee_hydro_site": 1,
"premier_mois_etiage_site": 1,
"statut_site": 1,
"surface_bv": 35878.0,
"type_contexte_loi_stat_site": [
1
],
"type_loi_site": [
0
],
"type_site": "STANDARD",
"uri_cours_eau": "http://id.eaufrance.fr/CEA/A---0000"
},
"restricted": false
}
]
},
"Observations": [
{
"@iot.selfLink": "http://frost-server/v1.1/Observations('0051bc74-ce9e-11f0-a1c9-eba64317e10c')",
"@iot.id": "0051bc74-ce9e-11f0-a1c9-eba64317e10c",
"phenomenonTime": "2025-12-01T09:00:00Z",
"resultTime": "2025-12-01T09:00:00Z",
"result": 5810.0,
"parameters": {
"code_continuite": 0,
"code_methode_obs": 0,
"code_qualification_obs": 16,
"code_site": "A0210050",
"code_station": "A021005050",
"code_statut": 4,
"code_systeme_alti_serie": 31,
"date_debut_serie": "2025-12-01T00:00:01Z",
"date_fin_serie": "2025-12-01T09:00:00Z",
"grandeur_hydro": "H",
"latitude": 47.556969907,
"libelle_continuite": "Continue",
"libelle_methode_obs": "Mesurée",
"libelle_qualification_obs": "Non qualifiée",
"libelle_statut": "Brute",
"longitude": 7.606153158
}
}
],
"Observations@iot.nextLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations?$top=1&$skip=1&$orderby=phenomenonTime+desc,%40iot.id+asc&$skipFilter=%28phenomenonTime+lt+2025-12-01T09%3A00%3A00Z%29",
"ObservedProperty@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/ObservedProperty",
"Sensor@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Sensor",
"Thing@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Thing",
"Observations@iot.navigationLink": "http://frost-server/v1.1/Datastreams('005124b2-ce9e-11f0-a1c9-83ad9e1e00e1')/Observations"
},
]
}Add $resultFormat=GeoJSON
And for readability, we $select only relevant attributes :
https://dev.api.deltatwin.gael.fr/v2.0/sensorthings/ObservedProperties('observed-property-H')/Datastreams?$top=1000&$expand=Thing($select=id,name;$expand=Locations($select=id,name,location)),Observations($orderby=phenomenonTime desc;$top=1;$select=id,result,phenomenonTime)&$resultFormat=GeoJSON