from fastapi import FastAPI, HTTPException, Depends, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from sqlalchemy.orm import Session from sqlalchemy import create_engine, Column, Integer, Float, String, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from datetime import datetime, timedelta import random import folium from folium.plugins import MarkerCluster DATABASE_URL = "sqlite:///./database.db" engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class WifiSignal(Base): __tablename__ = "wifi_signal" id = Column(Integer, primary_key=True, index=True) latitude = Column(Float, index=True) longitude = Column(Float, index=True) timestamp = Column(DateTime, index=True) signal_strength = Column(Integer) Base.metadata.create_all(bind=engine) app = FastAPI() templates = Jinja2Templates(directory="templates") def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/api/generate-data") def generate_data(db: Session = Depends(get_db)): base_latitude = 35.6837 base_longitude = 139.6805 start_date = datetime(2024, 8, 1) end_date = datetime(2024, 8, 7) delta = end_date - start_date for _ in range(100): random_days = random.randint(0, delta.days) random_seconds = random.randint(0, 86400) random_time = start_date + timedelta(days=random_days, seconds=random_seconds) random_latitude = base_latitude + random.uniform(-0.01, 0.01) random_longitude = base_longitude + random.uniform(-0.01, 0.01) random_signal_strength = random.randint(10, 50) wifi_signal = WifiSignal( latitude=random_latitude, longitude=random_longitude, timestamp=random_time, signal_strength=random_signal_strength ) db.add(wifi_signal) db.commit() return {"message": "Demo data generated successfully"} @app.delete("/api/delete-data") def delete_data(db: Session = Depends(get_db)): try: num_rows_deleted = db.query(WifiSignal).delete() db.commit() return {"message": f"Deleted {num_rows_deleted} rows from the database."} except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") @app.post("/api/upload") def upload_data(request: Request, db: Session = Depends(get_db)): data = request.json() latitude = data.get('latitude') longitude = data.get('longitude') timestamp = datetime.strptime(data.get('timestamp'), '%Y-%m-%d %H:%M:%S') signal_strength = data.get('signal_strength') wifi_signal = WifiSignal(latitude=latitude, longitude=longitude, timestamp=timestamp, signal_strength=signal_strength) db.add(wifi_signal) db.commit() return {"message": "Data uploaded successfully"} @app.get("/", response_class=HTMLResponse) def show_map(request: Request, start_date: str = None, end_date: str = None, db: Session = Depends(get_db)): query = db.query(WifiSignal) if start_date and end_date: start_datetime = datetime.strptime(start_date, '%Y-%m-%d') end_datetime = datetime.strptime(end_date, '%Y-%m-%d') query = query.filter(WifiSignal.timestamp >= start_datetime, WifiSignal.timestamp <= end_datetime) signals = query.all() signal_data = [(signal.latitude, signal.longitude, signal.signal_strength) for signal in signals] if signal_data: min_signal = min(s[2] for s in signal_data) max_signal = max(s[2] for s in signal_data) else: min_signal = max_signal = 1 m = folium.Map(location=[35.6837, 139.6805], zoom_start=12) marker_cluster = MarkerCluster().add_to(m) for lat, lon, signal_strength in signal_data: if max_signal - min_signal != 0: radius = 5 + 10 * ((signal_strength - min_signal) / (max_signal - min_signal)) else: radius = 15 folium.CircleMarker( location=[lat, lon], radius=radius, popup=f'Signal Strength: {signal_strength}', color='blue', fill=True, fill_opacity=0.6 ).add_to(marker_cluster) map_html = m._repr_html_() return templates.TemplateResponse("map.html", {"request": request, "map_html": map_html, "start_date": start_date, "end_date": end_date})