# main.py from fastapi import FastAPI, Form, UploadFile, File from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from filelock import FileLock import aiofiles import httpx import os from datetime import datetime import openpyxl # ------------------------- # Configuration # ------------------------- NEXTCLOUD_BASE_URL = "https://nextcloud.sdanywhere.com/remote.php/webdav/APs" NEXTCLOUD_USER = "kamaji" NEXTCLOUD_PASSWORD = "DvB0U2Uj3tOJaD" EXCEL_FILENAME = "ap_data.xlsx" LOCK_FILENAME = f"{EXCEL_FILENAME}.lock" app = FastAPI() # Allow CORS for frontend (if needed) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # ------------------------- # Utility: Upload file to Nextcloud # ------------------------- async def upload_to_nextcloud(local_path, remote_name): url = f"{NEXTCLOUD_BASE_URL}/{remote_name}" async with httpx.AsyncClient() as client: with open(local_path, "rb") as f: r = await client.put(url, content=f, auth=(NEXTCLOUD_USER, NEXTCLOUD_PASSWORD)) r.raise_for_status() # ------------------------- # Utility: Save Excel safely # ------------------------- def append_to_excel(data_row): lock = FileLock(LOCK_FILENAME) with lock: if not os.path.exists(EXCEL_FILENAME): wb = openpyxl.Workbook() ws = wb.active ws.append(["Timestamp", "Site ID", "AP Location", "Cable Length", "Serial Number"]) wb.save(EXCEL_FILENAME) wb = openpyxl.load_workbook(EXCEL_FILENAME) ws = wb.active ws.append(data_row) wb.save(EXCEL_FILENAME) # ------------------------- # Endpoint # ------------------------- @app.post("/api/ap/submit") async def submit_ap( site_id: str = Form(...), ap_location: str = Form(...), cable_length: float = Form(...), serial_number: str = Form(...), photo_continuity: UploadFile = File(...), photo_length: UploadFile = File(...), photo_verification: UploadFile = File(...), photo_close: UploadFile = File(...), photo_distance: UploadFile = File(...), ): # Capitalize serial number serial_number = serial_number.upper() # Create folder locally before upload folder_name = f"AP{ap_location}" os.makedirs(folder_name, exist_ok=True) # Save photos locally first photo_mapping = { "continuity": photo_continuity, "length": photo_length, "verification": photo_verification, "close": photo_close, "distance": photo_distance } saved_files = [] for key, file in photo_mapping.items(): filename = f"AP{ap_location}_{key}.jpg" local_path = os.path.join(folder_name, filename) async with aiofiles.open(local_path, "wb") as out_file: content = await file.read() await out_file.write(content) saved_files.append((local_path, filename)) # store for upload # Append data to Excel timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") data_row = [timestamp, site_id, ap_location, cable_length, serial_number] append_to_excel(data_row) # Upload Excel to Nextcloud await upload_to_nextcloud(EXCEL_FILENAME, EXCEL_FILENAME) # Upload photos to Nextcloud for local_path, remote_name in saved_files: await upload_to_nextcloud(local_path, remote_name) return JSONResponse(content={"site_id": site_id, "ap_location": ap_location})