diff --git a/api/grpc_getter.py b/api/grpc_getter.py index 619ca165..25047b3e 100644 --- a/api/grpc_getter.py +++ b/api/grpc_getter.py @@ -29,7 +29,7 @@ async def get_ts_ag_request(request): return response -async def get_spatial_extent(request): +async def get_extents_request(request): grpc_stub = get_grpc_stub() response = await grpc_stub.GetExtents(request) return response diff --git a/api/metadata_endpoints.py b/api/metadata_endpoints.py index 4739f13b..d82a9750 100644 --- a/api/metadata_endpoints.py +++ b/api/metadata_endpoints.py @@ -1,4 +1,6 @@ import logging +from datetime import datetime +from datetime import timezone from typing import Dict import datastore_pb2 as dstore @@ -11,6 +13,7 @@ from edr_pydantic.data_queries import EDRQuery from edr_pydantic.extent import Extent from edr_pydantic.extent import Spatial +from edr_pydantic.extent import Temporal from edr_pydantic.link import EDRQueryLink from edr_pydantic.link import Link from edr_pydantic.observed_property import ObservedProperty @@ -18,6 +21,7 @@ from edr_pydantic.unit import Unit from edr_pydantic.variables import Variables from fastapi import HTTPException +from grpc_getter import get_extents_request from grpc_getter import get_ts_ag_request @@ -25,6 +29,28 @@ logger.setLevel(logging.INFO) +def datetime_to_iso_string(value: datetime) -> str: + """Returns the datetime as ISO 8601 string. + Changes timezone +00:00 to the military time zone indicator (Z). + + Keyword arguments: + value -- A datetime + + Returns: + datetime string -- Returns the datetime as an ISO 8601 string with the military indicator. + """ + if value.tzinfo is None: + # This sort of replicates the functionality of Pydantic's AwareDatetime type + raise ValueError("Datetime object is not timezone aware") + + iso_8601_str = value.isoformat() + tz_offset_utc = "+00:00" + if iso_8601_str.endswith(tz_offset_utc): + return f"{iso_8601_str[:-len(tz_offset_utc)]}Z" + else: + return iso_8601_str + + def get_landing_page(request): return LandingPageModel( title="E-SOH EDR API", @@ -73,12 +99,28 @@ async def get_collection_metadata(base_url: str, is_self) -> Collection: all_parameters[ts.parameter_name] = parameter + extent_request = dstore.GetExtentsRequest() + extent_response = await get_extents_request(extent_request) + spatial_extent = extent_response.spatial_extent + interval_start = extent_response.temporal_extent.start.ToDatetime(tzinfo=timezone.utc) + interval_end = extent_response.temporal_extent.end.ToDatetime(tzinfo=timezone.utc) + collection = Collection( id="observations", links=[ Link(href=f"{base_url}/observations", rel="self" if is_self else "data"), ], - extent=Extent(spatial=Spatial(bbox=[[3.0, 50.0, 8.0, 55.0]], crs="WGS84")), # TODO: Get this from database + extent=Extent( + spatial=Spatial( + bbox=[[spatial_extent.left, spatial_extent.bottom, spatial_extent.right, spatial_extent.top]], + crs="EPSG:4326", + ), + temporal=Temporal( + interval=[[interval_start, interval_end]], + values=[f"{datetime_to_iso_string(interval_start)}/{datetime_to_iso_string(interval_end)}"], + trs="datetime", + ), + ), data_queries=DataQueries( position=EDRQuery( link=EDRQueryLink( diff --git a/api/routers/edr.py b/api/routers/edr.py index 47860023..d585f8a4 100644 --- a/api/routers/edr.py +++ b/api/routers/edr.py @@ -146,11 +146,11 @@ async def get_data_location_id( str | None, Query( alias="parameter-name", - example="wind_from_direction_2.0_mean_PT10M," - "wind_speed_2.0_mean_PT10M," - "relative_humidity_2.0_mean_PT1M," - "air_pressure_at_sea_level_2.0_mean_PT1M," - "air_temperature_2.0_minimum_PT10M", + example="wind_from_direction:2.0:mean:PT10M," + "wind_speed:10:mean:PT10M," + "relative_humidity:2.0:mean:PT1M," + "air_pressure_at_sea_level:1:mean:PT1M," + "air_temperature:1.5:maximum:PT10M", ), ] = None, datetime: Annotated[str | None, Query(example="2022-12-31T00:00Z/2023-01-01T00:00Z")] = None, @@ -186,11 +186,11 @@ async def get_data_position( str | None, Query( alias="parameter-name", - example="wind_from_direction_2.0_mean_PT10M," - "wind_speed_2.0_mean_PT10M," - "relative_humidity_2.0_mean_PT1M," - "air_pressure_at_sea_level_2.0_mean_PT1M," - "air_temperature_2.0_minimum_PT10M", + example="wind_from_direction:2.0:mean:PT10M," + "wind_speed:10:mean:PT10M," + "relative_humidity:2.0:mean:PT1M," + "air_pressure_at_sea_level:1:mean:PT1M," + "air_temperature:1.5:maximum:PT10M", ), ] = None, datetime: Annotated[str | None, Query(example="2022-12-31T00:00Z/2023-01-01T00:00Z")] = None, @@ -232,11 +232,11 @@ async def get_data_area( str | None, Query( alias="parameter-name", - example="wind_from_direction_2.0_mean_PT10M," - "wind_speed_2.0_mean_PT10M," - "relative_humidity_2.0_mean_PT1M," - "air_pressure_at_sea_level_2.0_mean_PT1M," - "air_temperature_2.0_minimum_PT10M", + example="wind_from_direction:2.0:mean:PT10M," + "wind_speed:10:mean:PT10M," + "relative_humidity:2.0:mean:PT1M," + "air_pressure_at_sea_level:1:mean:PT1M," + "air_temperature:1.5:maximum:PT10M", ), ] = None, datetime: Annotated[str | None, Query(example="2022-12-31T00:00Z/2023-01-01T00:00Z")] = None, diff --git a/api/routers/feature.py b/api/routers/feature.py index ff968b83..6968916f 100644 --- a/api/routers/feature.py +++ b/api/routers/feature.py @@ -9,8 +9,8 @@ from fastapi import Query from geojson_pydantic import Feature from geojson_pydantic import FeatureCollection +from grpc_getter import get_extents_request from grpc_getter import get_obs_request -from grpc_getter import get_spatial_extent from jinja2 import Environment from jinja2 import FileSystemLoader from jinja2 import select_autoescape @@ -122,7 +122,7 @@ async def get_time_series_by_id( async def get_dataset_metadata(): # need to get spatial extent. spatial_request = dstore.GetExtentsRequest() - extent = await get_spatial_extent(spatial_request) + extent = await get_extents_request(spatial_request) dynamic_fields = { "spatial_extents": [ [ diff --git a/datastore/integration-test/response/metadata_collections_all_collections.json b/datastore/integration-test/response/metadata_collections_all_collections.json index 3b10e372..d27c7636 100644 --- a/datastore/integration-test/response/metadata_collections_all_collections.json +++ b/datastore/integration-test/response/metadata_collections_all_collections.json @@ -18,13 +18,25 @@ "spatial": { "bbox": [ [ - 3.0, - 50.0, - 8.0, - 55.0 + -68.2758333, + 12.13, + 7.1493220605216, + 55.399166666667 ] ], - "crs": "WGS84" + "crs": "EPSG:4326" + }, + "temporal": { + "interval": [ + [ + "2022-12-31T00:00:00Z", + "2022-12-31T23:50:00Z" + ] + ], + "values": [ + "2022-12-31T00:00:00Z/2022-12-31T23:50:00Z" + ], + "trs": "datetime" } }, "data_queries": {