import pandas as pd import uvicorn from fastapi import FastAPI, Query, Response from fastapi.middleware.cors import CORSMiddleware from typing import Optional from datetime import date import io # --- Data Loading --- try: df = pd.read_csv( "q-fastapi-timeseries-cache.csv", parse_dates=["timestamp"] ) df['timestamp'] = df['timestamp'].dt.tz_localize(None) print("Application startup: Data loaded successfully.") except Exception as e: print(f"Application startup: An unexpected error occurred: {e}") df = pd.DataFrame(columns=['timestamp', 'location', 'sensor', 'value']) # --- App Setup --- app = FastAPI( title="SmartFactory IoT Sensor Analytics", description="API for querying and analyzing sensor data with caching." ) app_cache = {} app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # --- API Endpoint --- @app.get("/stats") async def get_stats( response: Response, location: Optional[str] = Query(None, description="Filter by location (e.g., 'zone-a')"), sensor: Optional[str] = Query(None, description="Filter by sensor type (e.g., 'temperature')"), start_date: Optional[date] = Query(None, description="Start date for filter (YYYY-MM-DD)"), end_date: Optional[date] = Query(None, description="End date for filter (YYYY-MM-DD)") ): cache_key = ( location, sensor, str(start_date) if start_date else None, str(end_date) if end_date else None ) if cache_key in app_cache: print(f"Cache HIT for key: {cache_key}") response.headers["X-Cache"] = "HIT" return {"stats": app_cache[cache_key]} print(f"Cache MISS for key: {cache_key}") response.headers["X-Cache"] = "MISS" try: filtered_df = df.copy() if location: filtered_df = filtered_df[filtered_df['location'] == location] if sensor: filtered_df = filtered_df[filtered_df['sensor'] == sensor] if start_date: filtered_df = filtered_df[filtered_df['timestamp'].dt.date >= start_date] if end_date: filtered_df = filtered_df[filtered_df['timestamp'].dt.date < end_date] if filtered_df.empty: stats = {"count": 0, "avg": None, "min": None, "max": None} else: value_series = filtered_df['value'] stats = { "count": int(value_series.count()), "avg": round(float(value_series.mean()), 2), "min": float(value_series.min()), "max": float(value_series.max()) } app_cache[cache_key] = stats return {"stats": stats} except Exception as e: print(f"Error during data processing: {e}") response.status_code = 500 return {"error": "An internal error occurred during data processing."} # --- Run the application --- if __name__ == "__main__": # IMPORTANT: Host must be '0.0.0.0' and port 7860 for Hugging Face Spaces print("Starting FastAPI server on http://0.0.0.0:7860") uvicorn.run("app:app", host="0.0.0.0", port=7860)