Spaces:
Sleeping
Sleeping
File size: 3,519 Bytes
0939b04 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | """SolarFit API μλ²."""
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
import httpx
from api.analysis import analyze
from api.models import AnalysisResult, ScanRequest, ScanResult
from api.config import VWORLD_API_KEY, VWORLD_SEARCH_URL
from api.scanner import scan_region
app = FastAPI(title="SolarFit API", version="0.1.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173", "http://localhost:5174", "http://localhost:3000", "https://solarfit-beta.vercel.app", "https://limtaek-solarfit-api.hf.space"],
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/api/health")
def health():
return {"status": "ok"}
@app.get("/api/analyze", response_model=AnalysisResult)
def analyze_location(
lat: float = Query(..., description="μλ (WGS84)", ge=33.0, le=39.0),
lon: float = Query(..., description="κ²½λ (WGS84)", ge=124.0, le=132.0),
):
"""μ’ν β νμκ΄ μ
μ§ λΆμ κ²°κ³Ό."""
try:
return analyze(lat=lat, lon=lon)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
def _vworld_search(q: str, search_type: str, category: str | None = None) -> list[dict]:
"""VWorld λ¨μΌ νμ
κ²μ β κ²°κ³Ό μμΌλ©΄ []."""
base = {
"service": "search",
"request": "search",
"key": VWORLD_API_KEY,
"query": q,
"type": search_type,
"format": "json",
"size": "5",
"crs": "EPSG:4326",
}
if category:
base["category"] = category
r = httpx.get(VWORLD_SEARCH_URL, params=base, timeout=10)
r.raise_for_status()
body = r.json()
if body.get("response", {}).get("status") != "OK":
return []
items = body.get("response", {}).get("result", {}).get("items", [])
results = []
for item in items:
addr = item.get("address", {})
label = addr.get("road") or addr.get("parcel") or ""
results.append({
"title": item.get("title") or label,
"address": label,
"lat": float(item.get("point", {}).get("y", 0)),
"lon": float(item.get("point", {}).get("x", 0)),
})
return results
@app.post("/api/scan", response_model=ScanResult)
def scan(req: ScanRequest):
try:
return scan_region(req.lat_min, req.lat_max, req.lon_min, req.lon_max, req.threshold)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/search")
def search_address(q: str = Query(..., description="μ£Όμ λλ μ₯μλͺ
")):
"""VWorld κ²μ API β μ₯μλͺ
Β·λλ‘λͺ
μ£Όμ β μ’ν."""
if not VWORLD_API_KEY:
return {"results": []}
try:
# μ₯μλͺ
(POI) κ²μ β category λΆνμ
place_results = _vworld_search(q, "PLACE")
# λλ‘λͺ
μ£Όμ κ²μ β category=ROAD νμ
road_results = _vworld_search(q, "ADDRESS", "ROAD")
seen: set[tuple] = set()
merged = []
for item in place_results + road_results:
key = (round(item["lat"], 5), round(item["lon"], 5))
if key not in seen:
seen.add(key)
merged.append(item)
if len(merged) >= 5:
break
return {"results": merged}
except (httpx.TimeoutException, httpx.RequestError, httpx.HTTPStatusError, ValueError, KeyError) as e:
raise HTTPException(status_code=502, detail=f"VWorld search error: {e}")
|