You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
5.9 KiB
Python

import os
from typing import Optional
import httpx
from fastapi import HTTPException, status
from sqlalchemy import Delete, desc, Select, select, func
from sqlalchemy.orm import selectinload
from src.aeros_equipment.service import save_default_equipment
from src.aeros_simulation.service import save_default_simulation_node
from src.auth.service import CurrentUser
from src.config import WINDOWS_AEROS_BASE_URL, AEROS_BASE_URL
from src.database.core import DbSession
from src.database.service import search_filter_sort_paginate
from .model import AerosProject
from .schema import AerosProjectInput
import asyncio
ALLOWED_EXTENSIONS = {".aro"}
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB
client = httpx.AsyncClient(timeout=300.0)
async def import_aro_project(*, db_session: DbSession, aeros_project_in: AerosProjectInput):
# windows_aeros_base_url = WINDOWS_AEROS_BASE_URL
file = aeros_project_in.aro_file
# Get filename
filename_without_ext = os.path.splitext(file.filename)[0]
# Get file extension
file_ext = os.path.splitext(file.filename)[1].lower()
# Validate file extension
if file_ext not in ALLOWED_EXTENSIONS:
raise HTTPException(
status_code=400,
detail=f"File type not allowed. Allowed: {ALLOWED_EXTENSIONS}"
)
print("read file")
# Read and check file size
content = await file.read()
if len(content) > MAX_FILE_SIZE:
raise HTTPException(
status_code=400,
detail="File too large. Max size: 100Mb"
)
# Project name hardcode
# project_name = "trialapi"
# Project name
project_name = filename_without_ext
## save File to windows app
# Output is string of file path, examole
# # Example response "C/dsad/dsad.aro"
try:
# Reset file position since we already read it for size check
# await file.seek(0)
# Prepare file for upload
files = {
"file": (file.filename, content, file.content_type or "application/octet-stream")
}
print("fetch")
response = await client.post(
f"{WINDOWS_AEROS_BASE_URL}/upload-file",
files=files
)
response.raise_for_status()
# Get the file path from the response
upload_result = response.json()
aro_path = upload_result.get("full_path")
filename = upload_result.get("stored_filename").replace(".aro", "")
if not aro_path:
raise HTTPException(
status_code=500,
detail="Failed to get file path from upload response"
)
except httpx.HTTPStatusError as e:
raise HTTPException(
status_code=e.response.status_code,
detail=f"Upload failed: {e.response.text}"
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
)
await asyncio.sleep(2)
# aro_path = r"C:/Users/user/Documents/Aeros/sample_project.aro"
aeros_project = AerosProject(project_name=filename, aro_file_path=aro_path)
# find aeros record first, if not found, then create a new one
stmt = select(AerosProject).order_by(desc(AerosProject.created_at)).limit(1)
result = await db_session.execute(stmt)
latest_project = result.scalar_one_or_none()
# If aeros record found, then update it
if latest_project:
latest_project.project_name = filename
latest_project.aro_file_path = aro_path
else: # else create new aeros record
db_session.add(aeros_project)
await db_session.commit()
# Update path to AEROS APP
# Example BODy "C/dsad/dsad.aro"
try:
response = await client.post(
f"{AEROS_BASE_URL}/api/Project/ImportAROFile",
content=f'"{aro_path}"',
headers={"Content-Type": "application/json"},
)
response.raise_for_status()
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
)
await _initialize_default_project_data(
db_session=db_session,
project_name=filename
)
async def fetch_aro_record(*, db_session: DbSession):
stmt = select(AerosProject).order_by(desc(AerosProject.updated_at)).limit(1)
result = await db_session.execute(stmt)
found_record = result.scalar_one_or_none()
return found_record
async def get_project(*, db_session: DbSession):
stmt = select(AerosProject).order_by(desc(AerosProject.updated_at)).limit(1)
result = await db_session.execute(stmt)
found_record = result.scalar_one_or_none()
return found_record
async def _initialize_default_project_data(
*,
db_session: DbSession,
project_name: str
) -> None:
"""
Initialize default equipment and simulation nodes for a project.
Args:
db_session: Database session
project_name: Name of the project to initialize
"""
try:
# Save default equipment
await save_default_equipment(
db_session=db_session,
project_name=project_name
)
# # Save default simulation node
# await save_default_simulation_node(
# db_session=db_session,
# project_name=project_name
# )
await db_session.commit()
except Exception as e:
await db_session.rollback()
raise e
async def reset_project(*, db_session: DbSession):
project = await fetch_aro_record(db_session=db_session)
try:
response = await client.post(
f"{AEROS_BASE_URL}/api/Project/ImportAROFile",
content=f'"{project.aro_file_path}"',
headers={"Content-Type": "application/json"},
)
response.raise_for_status()
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
)
return project.aro_file_path