Spaces:
Sleeping
Sleeping
| 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 --- | |
| 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) |