generated from mwc/lab_weather
88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
|
|
import requests
|
|
|
|
# -----------------------------------------------------------
|
|
# Geocode a text location (EX: "Boston, MA") using Nominatim
|
|
# -----------------------------------------------------------
|
|
def geocode_location(location):
|
|
url = "https://nominatim.openstreetmap.org/search"
|
|
params = {
|
|
"q": location,
|
|
"format": "json",
|
|
"limit": 1
|
|
}
|
|
|
|
response = requests.get(url, params=params, timeout=5)
|
|
data = response.json()
|
|
|
|
if not data:
|
|
raise ValueError(f"Could not geocode location: {location}")
|
|
|
|
return {
|
|
"lat": float(data[0]["lat"]),
|
|
"lng": float(data[0]["lon"])
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------
|
|
# Estimate user's coordinates using IP geolocation
|
|
# -----------------------------------------------------------
|
|
def estimate_location():
|
|
"""Estimate user's location using IP-based geolocation."""
|
|
try:
|
|
response = requests.get("https://ipinfo.io/json", timeout=5)
|
|
data = response.json()
|
|
|
|
if "loc" not in data:
|
|
raise RuntimeError("IP lookup returned no coordinates.")
|
|
|
|
lat_str, lng_str = data["loc"].split(",")
|
|
|
|
return {
|
|
"lat": float(lat_str),
|
|
"lng": float(lng_str)
|
|
}
|
|
except Exception as e:
|
|
raise RuntimeError(f"Could not estimate location: {e}")
|
|
|
|
|
|
# -----------------------------------------------------------
|
|
# Get the nearest weather office from NOAA API
|
|
# -----------------------------------------------------------
|
|
def get_weather_office(lat, lng):
|
|
url = f"https://api.weather.gov/points/{lat},{lng}"
|
|
response = requests.get(url, timeout=5)
|
|
data = response.json()
|
|
|
|
props = data["properties"]
|
|
return {
|
|
"office": props["gridId"],
|
|
"x": props["gridX"],
|
|
"y": props["gridY"]
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------
|
|
# Get NOAA forecast
|
|
# -----------------------------------------------------------
|
|
def get_forecast(office, x, y, metric=False):
|
|
url = f"https://api.weather.gov/gridpoints/{office}/{x},{y}/forecast"
|
|
response = requests.get(url, timeout=5)
|
|
data = response.json()
|
|
|
|
periods = data["properties"]["periods"]
|
|
|
|
# Convert NOAA data to your class format
|
|
forecast = []
|
|
for p in periods:
|
|
forecast.append({
|
|
"name": p["name"],
|
|
"description": p["detailedForecast"],
|
|
"temperature": p["temperature"] if not metric else round((p["temperature"] - 32) * 5/9),
|
|
"wind_speed": p["windSpeed"],
|
|
"wind_direction": p["windDirection"]
|
|
})
|
|
|
|
return forecast
|
|
|