MCP-Hackathon_Support / weather.py
bhardwaj08sarthak's picture
Update weather.py
3505383 verified
raw
history blame
8.32 kB
import requests
from geopy.geocoders import Nominatim
from datetime import datetime, date, timedelta
import pandas as pd
import gradio as gr
# Weather code to human-readable
WEATHER_CODES = {
0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
45: "Fog", 48: "Depositing rime fog", 51: "Light drizzle", 53: "Moderate drizzle", 55: "Dense drizzle",
61: "Slight rain", 63: "Moderate rain", 65: "Heavy rain", 71: "Slight snowfall", 73: "Moderate snowfall",
75: "Heavy snowfall", 80: "Slight rain showers", 81: "Moderate rain showers", 82: "Violent rain showers",
95: "Thunderstorm", 96: "Thunderstorm with hail"
}
def get_weather_forecast(location_name, target_date, include_hourly=False):
try:
if isinstance(target_date, str):
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
date_str = target_date.isoformat()
geolocator = Nominatim(user_agent="weather_api")
location = geolocator.geocode(location_name)
if not location:
return {"error": f"Could not find coordinates for '{location_name}'."}
lat, lon = location.latitude, location.longitude
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": lat,
"longitude": lon,
"daily": "sunrise,sunset,uv_index_max,temperature_2m_max,temperature_2m_min,weather_code",
"temperature_unit": "celsius",
"windspeed_unit": "kmh",
"timeformat": "iso8601",
"timezone": "auto",
"start_date": date_str,
"end_date": date_str
}
if include_hourly:
params["hourly"] = "temperature_2m,weather_code,uv_index,visibility"
response = requests.get(url, params=params)
if response.status_code != 200:
return {"error": f"API error {response.status_code}: {response.text}"}
raw = response.json()
if "daily" not in raw or date_str not in raw["daily"]["time"]:
return {"error": f"Weather data for {date_str} not available."}
idx = raw["daily"]["time"].index(date_str)
result = {
"date": date_str,
"sunrise": raw["daily"]["sunrise"][idx].split("T")[1],
"sunset": raw["daily"]["sunset"][idx].split("T")[1],
"uv_max": round(raw["daily"]["uv_index_max"][idx], 1),
"temp_min": round(raw["daily"]["temperature_2m_min"][idx]),
"temp_max": round(raw["daily"]["temperature_2m_max"][idx]),
"weather": WEATHER_CODES.get(int(raw["daily"]["weather_code"][idx]), "Unknown")
}
if include_hourly and "hourly" in raw:
hourly_df = pd.DataFrame({
"time": raw["hourly"]["time"],
"temp": raw["hourly"]["temperature_2m"],
"code": raw["hourly"]["weather_code"],
"uv": raw["hourly"]["uv_index"],
"visibility": [v / 1000 for v in raw["hourly"]["visibility"]]
})
hourly_df["time"] = pd.to_datetime(hourly_df["time"])
hourly_df = hourly_df[hourly_df["time"].dt.date == target_date]
hourly_df["weather"] = hourly_df["code"].apply(lambda c: WEATHER_CODES.get(int(c), "Unknown"))
result["hourly"] = [
{
"time": t.strftime("%Y-%m-%d %H:%M"),
"temp": f"{round(temp)}°C",
"weather": w,
"uv": round(uv, 1),
"visibility": f"{round(vis, 1)} km"
}
for t, temp, w, uv, vis in zip(
hourly_df["time"], hourly_df["temp"], hourly_df["weather"],
hourly_df["uv"], hourly_df["visibility"]
)
]
elif include_hourly:
result["note"] = "Hourly weather data unavailable for this date."
return result
except Exception as e:
return {"error": str(e)}
def get_weather_forecast_range(location_name, start_date, end_date):
try:
if isinstance(start_date, str):
start_date = datetime.strptime(start_date, "%Y-%m-%d").date()
if isinstance(end_date, str):
end_date = datetime.strptime(end_date, "%Y-%m-%d").date()
today = date.today()
days_ahead = (end_date - today).days
if days_ahead > 15:
return {"error": "Weather data only available up to 15 days from today."}
geolocator = Nominatim(user_agent="weather_api")
location = geolocator.geocode(location_name)
if not location:
return {"error": f"Could not find coordinates for '{location_name}'."}
lat, lon = location.latitude, location.longitude
include_hourly = days_ahead <= 6
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": lat,
"longitude": lon,
"daily": "sunrise,sunset,uv_index_max,temperature_2m_max,temperature_2m_min,weather_code",
"temperature_unit": "celsius",
"windspeed_unit": "kmh",
"timeformat": "iso8601",
"timezone": "auto",
"start_date": start_date.isoformat(),
"end_date": end_date.isoformat()
}
if include_hourly:
params["hourly"] = "temperature_2m,weather_code,uv_index,visibility"
response = requests.get(url, params=params)
if response.status_code != 200:
return {"error": f"API error {response.status_code}: {response.text}"}
raw = response.json()
forecasts = []
for idx, d in enumerate(raw["daily"]["time"]):
day_result = {
"date": d,
"sunrise": raw["daily"]["sunrise"][idx].split("T")[1],
"sunset": raw["daily"]["sunset"][idx].split("T")[1],
"uv_max": round(raw["daily"]["uv_index_max"][idx], 1),
"temp_min": round(raw["daily"]["temperature_2m_min"][idx]),
"temp_max": round(raw["daily"]["temperature_2m_max"][idx]),
"weather": WEATHER_CODES.get(int(raw["daily"]["weather_code"][idx]), "Unknown")
}
if include_hourly and "hourly" in raw:
hourly_df = pd.DataFrame({
"time": raw["hourly"]["time"],
"temp": raw["hourly"]["temperature_2m"],
"code": raw["hourly"]["weather_code"],
"uv": raw["hourly"]["uv_index"],
"visibility": [v / 1000 for v in raw["hourly"]["visibility"]]
})
hourly_df["time"] = pd.to_datetime(hourly_df["time"])
target_date = datetime.strptime(d, "%Y-%m-%d").date()
df_day = hourly_df[hourly_df["time"].dt.date == target_date]
df_day["weather"] = df_day["code"].apply(lambda c: WEATHER_CODES.get(int(c), "Unknown"))
day_result["hourly"] = [
{
"time": t.strftime("%Y-%m-%d %H:%M"),
"temp": f"{round(temp)}°C",
"weather": w,
"uv": round(uv, 1),
"visibility": f"{round(vis, 1)} km"
}
for t, temp, w, uv, vis in zip(
df_day["time"], df_day["temp"], df_day["weather"],
df_day["uv"], df_day["visibility"]
)
]
else:
day_result["note"] = "Hourly weather data is only available for the next 7 days."
forecasts.append(day_result)
return forecasts
except Exception as e:
return {"error": str(e)}
demo= gr.Interface(
fn=get_weather_forecast_range,
inputs=[
gr.Textbox(label="Location Name", placeholder="Enter a city or place name"),
gr.Textbox(label="Start Date (YYYY-MM-DD)", value=date.today()),
gr.Textbox(label="End Date (YYYY-MM-DD)", value=date.today() + timedelta(days=6))
],
outputs=gr.JSON(label="Weather Forecast"),
title="Weather Forecast Tool",
description="Get weather forecasts for a specific location and date range."
)
demo.launch(mcp_server=True, share=True)