Skip to content

Commit e5c5e75

Browse files
committed
add fetch list of mosmix stations by radius
1 parent 8914ffe commit e5c5e75

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

app/api/climate.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from ..dependencies import get_session
88
from ..services.climate import (
99
get_dwd_stations_by_municipality_key,
10+
get_mosmix_geometries_by_lat_lng,
1011
get_mosmix_geometries_by_bbox,
1112
get_weather_service_stations,
1213
get_all_mosmix_stations
@@ -152,3 +153,53 @@ async def fetch_mosmix_geometries_by_bbox(
152153
geojson_data = FeatureCollection(features, crs=crs)
153154

154155
return geojson_data
156+
157+
158+
@route_climate.get(
159+
'/mosmix/radius',
160+
response_model=dict,
161+
tags=['Deutscher Wetterdienst'],
162+
description=(
163+
'Retrieves a list of German weather service stations within the '
164+
'specified radius.'
165+
),
166+
responses={
167+
200: {'description': 'OK'},
168+
400: {'description': 'Bad Request'},
169+
404: {'description': 'Not Found'},
170+
422: {'description': 'Unprocessable Entity'},
171+
}
172+
)
173+
async def fetch_mosmix_geometries_by_lat_lng(
174+
lat: float,
175+
lng: float,
176+
radius: float = Query(
177+
default=5000,
178+
ge=0,
179+
le=100000,
180+
description='Radius in meters'
181+
),
182+
session: AsyncSession = Depends(get_session)
183+
):
184+
rows = await get_mosmix_geometries_by_lat_lng(session, lat, lng, radius)
185+
186+
if len(rows) == 0:
187+
raise HTTPException(
188+
status_code=status.HTTP_404_NOT_FOUND,
189+
detail=f'No matches found for coordinates ({lat}, {lng})'
190+
)
191+
192+
features = [
193+
Feature(
194+
id=row['station_id'],
195+
geometry=row['geojson'],
196+
properties={'station_name': row['station_name']},
197+
)
198+
for row in rows
199+
]
200+
201+
crs = {'type': 'name', 'properties': {
202+
'name': 'urn:ogc:def:crs:OGC:1.3:CRS84'}}
203+
geojson_data = FeatureCollection(features, crs=crs)
204+
205+
return geojson_data

app/services/climate.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sqlalchemy.ext.asyncio import AsyncSession
55
from sqlalchemy.future import select
66
from sqlalchemy.orm import aliased
7+
from geoalchemy2 import Geography as GEOGRAPHY
78

89
from ..utils.validators import validate_not_none
910
from ..utils.sanitizer import sanitize_string
@@ -143,3 +144,45 @@ async def get_mosmix_geometries_by_bbox(
143144
rows = result.mappings().all()
144145

145146
return rows
147+
148+
149+
async def get_mosmix_geometries_by_lat_lng(
150+
session: AsyncSession,
151+
lat: float,
152+
lng: float,
153+
radius: float
154+
):
155+
model = MosmixStation
156+
157+
geojson = cast(func.ST_AsGeoJSON(
158+
model.wkb_geometry, 15), JSON).label('geojson')
159+
160+
point = func.ST_SetSRID(func.ST_MakePoint(
161+
bindparam('lng'),
162+
bindparam('lat')
163+
), 4326)
164+
165+
stmt = (
166+
select(
167+
model.station_id,
168+
model.station_name,
169+
geojson
170+
)
171+
.where(
172+
func.ST_DWithin(
173+
cast(model.wkb_geometry, GEOGRAPHY),
174+
cast(point, GEOGRAPHY),
175+
bindparam('radius')
176+
),
177+
func.ST_IsValid(model.wkb_geometry)
178+
)
179+
)
180+
181+
result = await session.execute(
182+
stmt,
183+
{'lat': lat, 'lng': lng, 'radius': radius}
184+
)
185+
186+
rows = result.mappings().all()
187+
188+
return rows

0 commit comments

Comments
 (0)