Parsovani GPX

This commit is contained in:
Michal Kváček
2023-09-04 15:34:08 +02:00
parent f7d1bbb6dd
commit ed5df4f953
9 changed files with 194 additions and 22 deletions
+30 -17
View File
@@ -1,5 +1,5 @@
import asyncio
from datetime import timedelta
from datetime import timedelta, datetime
from typing import List, Optional, Annotated, TYPE_CHECKING, Tuple
import strawberry
from fastapi import HTTPException
@@ -11,6 +11,7 @@ from database import models
from database.models import flight_has_copilot
from decorators.endpoints import authenticated_user_only
from decorators.error_logging import error_logging
from external.gpx_parser import GPXParser
from graphql_schema.dataloaders.aircraft import aircraft_dataloader
from graphql_schema.dataloaders.airport import airport_dataloader
from graphql_schema.dataloaders.copilots import flight_copilots_dataloader
@@ -23,7 +24,7 @@ from graphql_schema.entities.photo import Photo
from graphql_schema.entities.poi import PointOfInterest
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_type, strawberry_sqlalchemy_input
from upload_utils import get_public_url
from .helpers.flight import handle_aircraft_save, handle_track_edit, handle_copilots_edit, handle_weather_info, get_airports, handle_upload_gpx, handle_airport_changed
from .helpers.flight import handle_aircraft_save, handle_track_edit, handle_copilots_edit, handle_weather_info, get_airports, handle_upload_gpx, handle_airport_changed, add_terrain_elevation
from ..types import ComboboxInput
if TYPE_CHECKING:
@@ -51,10 +52,16 @@ class Point:
@strawberry.type
class GPXTrack:
points: List[Point]
coordinates: List[Point]
speed: List[float]
elevation: List[float]
altitude: List[float]
magnetic_variation: List[float]
terrain_elevation: List[float]
time: List[datetime]
max_speed: float
avg_speed: float
max_altitude: float
avg_altitude: float
@strawberry_sqlalchemy_type(models.Flight)
@@ -97,18 +104,22 @@ class Flight:
if not root.gpx_track_filename:
return None
path = "/app/uploads/tracks"
try:
gpx_parser = GPXParser(f"/app/uploads/tracks/{root.gpx_track_filename}")
except OSError:
return None
tree = etree.parse(f"{path}/{root.gpx_track_filename}")
points = tree.findall("//trk")
speed = tree.xpath("//extensions/speed")
elevation = tree.xpath('//ele')
print(tree.getroot().find("trk"), list(points), speed, elevation)
return GPXTrack(
points=[Point(lat=50.123, lng=14.324243)],
speed=[],
elevation=[],
terrain_elevation=[]
coordinates=[Point(**point) for point in await gpx_parser.get_coordinates()],
speed=await gpx_parser.get_speed(),
altitude=await gpx_parser.get_altitude(),
terrain_elevation=await gpx_parser.get_terrain_elevation(),
time=await gpx_parser.get_times(),
max_speed=await gpx_parser.get_max_speed(),
avg_speed=await gpx_parser.get_avg_speed(),
max_altitude=await gpx_parser.get_max_altitude(),
avg_altitude=await gpx_parser.get_avg_altitude(),
magnetic_variation=await gpx_parser.get_magnetic_variation(),
)
def load_gpx_track_url(root):
@@ -131,7 +142,7 @@ class Flight:
takeoff_weather_info: Optional[WeatherInfo] = strawberry.field(resolver=load_takeoff_weather_info)
landing_weather_info: Optional[WeatherInfo] = strawberry.field(resolver=load_landing_weather_info)
photos: List[Photo] = strawberry.field(resolver=load_photos)
gpx_track_url: Optional[str] = strawberry.field(resolver=load_gpx_track_url)
gpx_track_url: Optional[str] = strawberry.field(resolver=load_gpx_track_url) # TODO: odstranit
gpx_track: Optional[GPXTrack] = strawberry.field(resolver=load_gpx_track)
@@ -222,8 +233,8 @@ class CreateFlightMutation:
@strawberry.type
class EditFlightMutation:
@strawberry_sqlalchemy_input(models.Flight, exclude_fields=[
"id", "aircraft_id", "deleted", "landing_airport_id", "takeoff_airport_id"
"takeoff_weather_info_id", "landing_weather_info_id", "gpx_track_filename"
"id", "aircraft_id", "deleted", "landing_airport_id", "takeoff_airport_id",
"takeoff_weather_info_id", "landing_weather_info_id", "gpx_track_filename"
], all_optional=True)
class EditFlightInput:
gpx_track: Optional[Upload] = None # TODO: poresit validaci uploadovaneho souboru!
@@ -253,7 +264,9 @@ class EditFlightMutation:
if input.gpx_track is not None:
data['gpx_track_filename'] = await handle_upload_gpx(flight, input.gpx_track)
info.context.background_tasks.add_task(add_terrain_elevation, flight=flight, gpx_filename=data['gpx_track_filename'], db=db)
# TODO: nasledujici metody volat i pokud se zmenil cas vzletu!
if input.takeoff_airport and input.takeoff_airport.id != flight.takeoff_airport_id:
await handle_airport_changed(
db,
+29 -2
View File
@@ -1,11 +1,16 @@
import asyncio
from datetime import datetime
from typing import List, Type, Literal, Optional, Tuple
from aiohttp import ClientResponseError
from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.background import BackgroundTasks
from strawberry.file_uploads import Upload
from database import models
from external.elevation import ElevationAPI
from external.gpx_parser import GPXParser
from external.weather import Weather
from graphql_schema.types import ComboboxInput
from upload_utils import delete_file, file_exists, handle_file_upload
@@ -111,11 +116,33 @@ async def handle_airport_changed(
setattr(flight, f"{type_}_datetime", input_datetime)
async def add_terrain_elevation(db: AsyncSession, flight: models.Flight, gpx_filename: str):
path = "/app/uploads/tracks" # TODO vytahnout do configu
elevation_api = ElevationAPI()
gpx_parser = GPXParser(f"{path}/{gpx_filename}")
coordinates = await gpx_parser.get_coordinates()
print("AAAAAAAAAAAAAAAAAAAAAAAAA", coordinates)
try:
elevation = await elevation_api.get_elevation_for_points(coordinates)
print("ELEVATION", elevation)
tree_with_elevation = gpx_parser.add_terrain_elevation(elevation)
output_name = f"terrain_{gpx_filename}"
gpx_parser.write(tree_with_elevation, f"{path}/{output_name}")
await models.Flight.update(db, {"gpx_track_filename": output_name}, obj=flight)
except ClientResponseError:
print("NEumim elevation!")
async def handle_upload_gpx(flight: models.Flight, gpx_track: Upload):
path = "/app/uploads/tracks"
if flight.gpx_track_filename and file_exists(path + "/" + flight.gpx_track_filename):
delete_file(path + "/" + flight.gpx_track_filename)
if flight.gpx_track_filename:
delete_file(path + "/" + flight.gpx_track_filename, silent=True)
return await handle_file_upload(gpx_track, path)