modified: app.py
new file: static/styles.css modified: templates/index.html
This commit is contained in:
47
app.py
47
app.py
@@ -1,59 +1,52 @@
|
|||||||
from flask import Flask, jsonify, request, render_template
|
from flask import Flask, jsonify, request, render_template
|
||||||
from wetterdienst.provider.dwd.forecast import DWDForecastRequest
|
from wetterdienst.provider.dwd.observation import DwdObservationRequest, DwdObservationResolution
|
||||||
from wetterdienst.provider.dwd.metadata import DWDStationParameter
|
|
||||||
from wetterdienst.provider.dwd.metadata.resolution import Resolution
|
|
||||||
from wetterdienst.util.geo import Coordinates
|
from wetterdienst.util.geo import Coordinates
|
||||||
from geopy.geocoders import Nominatim
|
from geopy.geocoders import Nominatim
|
||||||
import os
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='static', template_folder='templates')
|
app = Flask(__name__, static_folder='static', template_folder='templates')
|
||||||
|
|
||||||
# Funktion, um die Koordinaten anhand eines Ortsnamens oder einer PLZ zu erhalten
|
# Function to get coordinates based on the user location
|
||||||
def get_coordinates(location):
|
def get_coordinates(location):
|
||||||
geolocator = Nominatim(user_agent="wetterdienst")
|
geolocator = Nominatim(user_agent="wetterdienst_app")
|
||||||
location = geolocator.geocode(location)
|
location = geolocator.geocode(location)
|
||||||
if location:
|
if location:
|
||||||
return Coordinates(location.latitude, location.longitude)
|
return Coordinates(location.latitude, location.longitude)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Funktion, um Wetterdaten von der DWD-API basierend auf den Koordinaten zu erhalten
|
# Function to get weather data from DWD API
|
||||||
def get_weather_data(location):
|
def get_weather_data(location):
|
||||||
coords = get_coordinates(location)
|
coords = get_coordinates(location)
|
||||||
if not coords:
|
if not coords:
|
||||||
return {"error": "Ort nicht gefunden."}
|
return {"error": "Location not found."}
|
||||||
|
|
||||||
# DWD-Anfrage für die nächsten 10 Tage
|
request = DwdObservationRequest(
|
||||||
request = DWDForecastRequest(
|
parameter=["temperature_air_mean_200", "precipitation_height", "wind_speed"],
|
||||||
parameter=[DWDStationParameter.TEMPERATURE_AIR_MEAN_200, DWDStationParameter.WIND_SPEED, DWDStationParameter.PRECIPITATION_HEIGHT],
|
resolution=DwdObservationResolution.HOURLY,
|
||||||
resolution=Resolution.HOURLY,
|
start_date=(datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d"),
|
||||||
coordinates=coords
|
end_date=(datetime.now() + timedelta(days=10)).strftime("%Y-%m-%d")
|
||||||
)
|
)
|
||||||
|
|
||||||
forecast = request.values.all().df
|
stations = request.filter_by_distance(latlon=(coords.latitude, coords.longitude), distance=30)
|
||||||
|
values = stations.values.all().df
|
||||||
|
|
||||||
weather_data = []
|
if values.empty:
|
||||||
for _, row in forecast.iterrows():
|
return {"error": "No data available for the selected location."}
|
||||||
weather_data.append({
|
|
||||||
"date": row["datetime"].strftime("%Y-%m-%d"),
|
|
||||||
"temperature": row["temperature_air_mean_200"],
|
|
||||||
"wind_speed": row["wind_speed"],
|
|
||||||
"precipitation": row["precipitation_height"],
|
|
||||||
"cloud_cover": row.get("cloud_cover", 0) # Wenn nicht verfügbar, setze auf 0
|
|
||||||
})
|
|
||||||
|
|
||||||
|
weather_data = values.to_dict(orient='records')
|
||||||
return weather_data
|
return weather_data
|
||||||
|
|
||||||
# Route für die Startseite
|
# Route for rendering the HTML frontend
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
# API für die Wetterdaten
|
# API endpoint for fetching weather data based on user input
|
||||||
@app.route('/api/weather')
|
@app.route('/api/weather', methods=['GET'])
|
||||||
def weather():
|
def weather():
|
||||||
location = request.args.get('location')
|
location = request.args.get('location')
|
||||||
if not location:
|
if not location:
|
||||||
return jsonify({"error": "Ort nicht angegeben."}), 400
|
return jsonify({"error": "Please provide a location."}), 400
|
||||||
|
|
||||||
data = get_weather_data(location)
|
data = get_weather_data(location)
|
||||||
if "error" in data:
|
if "error" in data:
|
||||||
|
|||||||
27
static/styles.css
Normal file
27
static/styles.css
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location-input {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-day {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
@@ -1,48 +1,51 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Wettervorhersage</title>
|
<title>Weather Forecast</title>
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
<link rel="stylesheet" href="/static/styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Wettervorhersage für 10 Tage</h1>
|
<h1>10-Day Weather Forecast</h1>
|
||||||
|
|
||||||
<!-- Eingabefeld für den Ort -->
|
<!-- Input for location -->
|
||||||
<div class="location-input">
|
<div class="location-input">
|
||||||
<label for="location">Geben Sie einen Ort ein:</label>
|
<label for="location">Enter a location (city or coordinates):</label>
|
||||||
<input type="text" id="location" placeholder="Stadt oder PLZ">
|
<input type="text" id="location" placeholder="City or coordinates">
|
||||||
<button onclick="loadWeatherData()">Wetter anzeigen</button>
|
<button onclick="loadWeatherData()">Get Weather</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Wetteranzeige -->
|
<!-- Weather display -->
|
||||||
<div class="weather-container" id="weather-container"></div>
|
<div class="weather-container" id="weather-container"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
async function loadWeatherData() {
|
async function loadWeatherData() {
|
||||||
const location = document.getElementById('location').value;
|
const location = document.getElementById('location').value;
|
||||||
if (!location) {
|
if (!location) {
|
||||||
alert('Bitte geben Sie einen Ort ein!');
|
alert('Please provide a location.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch Wetterdaten basierend auf dem eingegebenen Ort
|
|
||||||
const response = await fetch(`/api/weather?location=${location}`);
|
const response = await fetch(`/api/weather?location=${location}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// Wetterdaten in der HTML anzeigen
|
|
||||||
const container = document.getElementById('weather-container');
|
const container = document.getElementById('weather-container');
|
||||||
container.innerHTML = ''; // Vorherige Daten löschen
|
container.innerHTML = ''; // Clear previous data
|
||||||
|
|
||||||
|
if (data.error) {
|
||||||
|
container.innerHTML = `<p>Error: ${data.error}</p>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data.forEach(day => {
|
data.forEach(day => {
|
||||||
const dayDiv = document.createElement('div');
|
const dayDiv = document.createElement('div');
|
||||||
dayDiv.className = 'weather-day';
|
dayDiv.className = 'weather-day';
|
||||||
dayDiv.innerHTML = `
|
dayDiv.innerHTML = `
|
||||||
<h3>${day.date}</h3>
|
<h3>Date: ${day.date}</h3>
|
||||||
<p>Temperatur: ${day.temperature}°C</p>
|
<p>Temperature: ${day.temperature_air_mean_200} °C</p>
|
||||||
<p>Wind: ${day.wind_speed} km/h</p>
|
<p>Precipitation: ${day.precipitation_height} mm</p>
|
||||||
<p>Niederschlag: ${day.precipitation} mm</p>
|
<p>Wind Speed: ${day.wind_speed} km/h</p>
|
||||||
<p>Wolken: ${day.cloud_cover}%</p>
|
|
||||||
`;
|
`;
|
||||||
container.appendChild(dayDiv);
|
container.appendChild(dayDiv);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user