| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from app.routes import auth, users, satellite, analytics, maps, action_plan, data, health, analysis, green_gap, time_machine |
|
|
| app = FastAPI( |
| title="Satellite Environmental Intelligence Platform", |
| description="AETRIX 2026 β PS-4: Satellite data analytics for smart cities", |
| version="1.0.0", |
| ) |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=False, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| app.include_router(health.router, prefix="/api/v1", tags=["Health"]) |
| app.include_router(auth.router, prefix="/api/v1/auth", tags=["Auth"]) |
| app.include_router(users.router, prefix="/api/v1/users", tags=["Users"]) |
| app.include_router(satellite.router, prefix="/api/v1/satellite", tags=["Satellite"]) |
| app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["Analytics"]) |
| app.include_router(maps.router, prefix="/api/v1/maps", tags=["Maps"]) |
| app.include_router(action_plan.router, prefix="/api/v1/action-plan", tags=["Action Plan"]) |
| app.include_router(data.router, prefix="/api/v1/data", tags=["Data"]) |
| app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["Specialized Analysis"]) |
| app.include_router(green_gap.router, prefix="/api/v1/green-gap", tags=["Green Gap Analysis"]) |
| app.include_router(time_machine.router, prefix="/api/v1/time-machine", tags=["Time Machine"]) |
|
|
| @app.on_event("startup") |
| async def startup(): |
| |
| try: |
| from app.models.db_models import create_tables, get_engine |
| engine = get_engine() |
| if engine: |
| await create_tables() |
| print("PostgreSQL + PostGIS connected, tables ready") |
| else: |
| print("No DATABASE_URL configured β using in-memory fallback") |
| except Exception as e: |
| print(f"Database setup skipped: {e} β using in-memory fallback") |
|
|
| print("Satellite Environmental Intelligence Platform started") |
|
|
| |
| import threading |
| threading.Thread(target=_warmup_caches, daemon=True).start() |
|
|
|
|
| def _warmup_caches(): |
| """Pre-load all data + run ML models for all 14 cities at startup.""" |
| import time |
| start = time.time() |
|
|
| try: |
| from app.utils.cities import CITIES |
| from app.services import satellite_service, ml_service |
|
|
| params = ["LST", "NDVI", "NO2", "SO2", "CO", "O3", "AEROSOL", "SOIL_MOISTURE"] |
| ml_params = ["LST", "NDVI", "NO2", "SOIL_MOISTURE"] |
| city_keys = list(CITIES.keys()) |
|
|
| print(f"[WARMUP] Pre-loading data for {len(city_keys)} cities...") |
|
|
| for i, city_key in enumerate(city_keys): |
| |
| for param in params: |
| try: |
| satellite_service._load_data(param, city_key) |
| except Exception: |
| pass |
|
|
| |
| for param in params: |
| try: |
| satellite_service.get_heatmap_data(param, city_key) |
| except Exception: |
| pass |
|
|
| |
| for param in params: |
| try: |
| satellite_service.get_timeseries(param, city_key) |
| except Exception: |
| pass |
|
|
| |
| for param in ml_params: |
| try: |
| ml_service.detect_anomalies(param, city_key) |
| except Exception: |
| pass |
| try: |
| ml_service.find_hotspots(param, city_key) |
| except Exception: |
| pass |
|
|
| |
| try: |
| ml_service.get_city_summary(city_key) |
| except Exception: |
| pass |
|
|
| print(f"[WARMUP] {city_key} done ({i+1}/{len(city_keys)})") |
|
|
| |
| try: |
| from app.services import cache_service |
| cache_service.set_last_synced() |
| except Exception: |
| pass |
|
|
| elapsed = round(time.time() - start, 1) |
| print(f"[WARMUP] All {len(city_keys)} cities cached in {elapsed}s β ready for instant responses") |
|
|
| except Exception as e: |
| print(f"[WARMUP] Cache warmup error: {e}") |
|
|
| @app.on_event("shutdown") |
| async def shutdown(): |
| print("Shutting down...") |
|
|