weeee💃
This commit is contained in:
commit
5dc71dbf90
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Use Python 3.9 as the base image
|
||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy requirements and install dependencies
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy the application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
CMD ["python", "main.py"]
|
29
config.py
Normal file
29
config.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Load environment variables
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# DB API Configuration
|
||||||
|
DB_API_KEY = os.getenv("DB_API_KEY")
|
||||||
|
DB_API_URL = "https://api.deutschebahn.com/fahrplan-plus/v1"
|
||||||
|
|
||||||
|
# Weather API Configuration
|
||||||
|
WEATHER_API_KEY = os.getenv("WEATHER_API_KEY")
|
||||||
|
WEATHER_API_URL = "https://api.openweathermap.org/data/2.5/weather"
|
||||||
|
|
||||||
|
# Database Configuration
|
||||||
|
DB_HOST = os.getenv("DB_HOST", "localhost")
|
||||||
|
DB_PORT = os.getenv("DB_PORT", "5432")
|
||||||
|
DB_NAME = os.getenv("DB_NAME", "train_weather_db")
|
||||||
|
DB_USER = os.getenv("DB_USER", "postgres")
|
||||||
|
DB_PASSWORD = os.getenv("DB_PASSWORD", "password")
|
||||||
|
|
||||||
|
# Station IDs (example values; validate via DB API)
|
||||||
|
STATION_IDS = {
|
||||||
|
"Frankfurt": "008000105",
|
||||||
|
"Berlin": "8010169",
|
||||||
|
"München": "008000000",
|
||||||
|
"Köln": "008000333",
|
||||||
|
"Stuttgart": "008000456"
|
||||||
|
}
|
106
database.py
Normal file
106
database.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import psycopg2
|
||||||
|
from psycopg2 import sql
|
||||||
|
from config import DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
|
||||||
|
|
||||||
|
def get_db_connection():
|
||||||
|
"""Connect to the PostgreSQL database."""
|
||||||
|
return psycopg2.connect(
|
||||||
|
host=DB_HOST,
|
||||||
|
port=DB_PORT,
|
||||||
|
dbname=DB_NAME,
|
||||||
|
user=DB_USER,
|
||||||
|
password=DB_PASSWORD
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_tables():
|
||||||
|
"""Create database tables if they don't exist."""
|
||||||
|
commands = [
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS trains (
|
||||||
|
train_id VARCHAR PRIMARY KEY,
|
||||||
|
train_type VARCHAR,
|
||||||
|
model VARCHAR,
|
||||||
|
capacity INT,
|
||||||
|
age_years FLOAT,
|
||||||
|
maintenance_history JSONB,
|
||||||
|
technical_specs JSONB
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS schedules (
|
||||||
|
schedule_id UUID PRIMARY KEY,
|
||||||
|
train_id VARCHAR,
|
||||||
|
route_id VARCHAR,
|
||||||
|
departure_station VARCHAR,
|
||||||
|
arrival_station VARCHAR,
|
||||||
|
scheduled_departure TIMESTAMP,
|
||||||
|
scheduled_arrival TIMESTAMP,
|
||||||
|
platform_departure VARCHAR,
|
||||||
|
platform_arrival VARCHAR,
|
||||||
|
distance_km FLOAT,
|
||||||
|
scheduled_stops INT,
|
||||||
|
service_type VARCHAR,
|
||||||
|
FOREIGN KEY (train_id) REFERENCES trains(train_id)
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS actual_journeys (
|
||||||
|
journey_id UUID PRIMARY KEY,
|
||||||
|
schedule_id UUID,
|
||||||
|
actual_departure TIMESTAMP,
|
||||||
|
actual_arrival TIMESTAMP,
|
||||||
|
actual_platform_departure VARCHAR,
|
||||||
|
actual_platform_arrival VARCHAR,
|
||||||
|
delay_departure_minutes INT,
|
||||||
|
delay_arrival_minutes INT,
|
||||||
|
cancellation_flag BOOLEAN,
|
||||||
|
cancellation_reason VARCHAR,
|
||||||
|
passenger_count INT,
|
||||||
|
load_factor FLOAT,
|
||||||
|
FOREIGN KEY (schedule_id) REFERENCES schedules(schedule_id)
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS stations (
|
||||||
|
station_id VARCHAR PRIMARY KEY,
|
||||||
|
station_name VARCHAR,
|
||||||
|
latitude FLOAT,
|
||||||
|
longitude FLOAT,
|
||||||
|
elevation FLOAT,
|
||||||
|
number_of_platforms INT,
|
||||||
|
daily_passenger_volume INT,
|
||||||
|
station_category INT,
|
||||||
|
facilities JSONB,
|
||||||
|
connection_types JSONB
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS weather_history (
|
||||||
|
weather_id UUID PRIMARY KEY,
|
||||||
|
station_id VARCHAR,
|
||||||
|
timestamp TIMESTAMP,
|
||||||
|
temperature FLOAT,
|
||||||
|
precipitation FLOAT,
|
||||||
|
wind_speed FLOAT,
|
||||||
|
wind_direction INT,
|
||||||
|
humidity FLOAT,
|
||||||
|
pressure FLOAT,
|
||||||
|
visibility FLOAT,
|
||||||
|
weather_condition VARCHAR,
|
||||||
|
FOREIGN KEY (station_id) REFERENCES stations(station_id)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
]
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = get_db_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
for command in commands:
|
||||||
|
cur.execute(command)
|
||||||
|
cur.close()
|
||||||
|
conn.commit()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating tables: {e}")
|
||||||
|
finally:
|
||||||
|
if conn is not None:
|
||||||
|
conn.close()
|
7
env.env
Normal file
7
env.env
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
DB_API_KEY=your_db_api_key
|
||||||
|
WEATHER_API_KEY=your_weather_api_key
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=train_weather_db
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=password
|
90
main.py
Normal file
90
main.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import requests
|
||||||
|
import uuid
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||||
|
from database import get_db_connection, create_tables
|
||||||
|
from config import DB_API_KEY, DB_API_URL, WEATHER_API_KEY, WEATHER_API_URL, STATION_IDS
|
||||||
|
|
||||||
|
# Initialize scheduler
|
||||||
|
scheduler = BlockingScheduler()
|
||||||
|
|
||||||
|
def fetch_train_schedules():
|
||||||
|
"""Fetch train schedules from DB API."""
|
||||||
|
for station_name, station_id in STATION_IDS.items():
|
||||||
|
url = f"{DB_API_URL}/departureBoard?station={station_id}"
|
||||||
|
headers = {"Authorization": f"Bearer {DB_API_KEY}"}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code == 200:
|
||||||
|
schedules = response.json()
|
||||||
|
store_schedules(schedules, station_id)
|
||||||
|
else:
|
||||||
|
print(f"Failed to fetch schedules for {station_name}: {response.status_code}")
|
||||||
|
|
||||||
|
def store_schedules(schedules, station_id):
|
||||||
|
"""Store schedules in the database."""
|
||||||
|
conn = get_db_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
for schedule in schedules:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO schedules (
|
||||||
|
schedule_id, train_id, route_id, departure_station, arrival_station,
|
||||||
|
scheduled_departure, scheduled_arrival, platform_departure, platform_arrival,
|
||||||
|
distance_km, scheduled_stops, service_type
|
||||||
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
str(uuid.uuid4()), schedule.get("train_id"), schedule.get("route_id"),
|
||||||
|
station_id, schedule.get("arrival_station"),
|
||||||
|
schedule.get("scheduled_departure"), schedule.get("scheduled_arrival"),
|
||||||
|
schedule.get("platform_departure"), schedule.get("platform_arrival"),
|
||||||
|
schedule.get("distance_km"), schedule.get("scheduled_stops"),
|
||||||
|
schedule.get("service_type")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def fetch_weather_data():
|
||||||
|
"""Fetch weather data for each station."""
|
||||||
|
for station_name, station_id in STATION_IDS.items():
|
||||||
|
url = f"{WEATHER_API_URL}?lat={STATION_LATITUDE}&lon={STATION_LONGITUDE}&appid={WEATHER_API_KEY}"
|
||||||
|
response = requests.get(url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
weather = response.json()
|
||||||
|
store_weather_data(weather, station_id)
|
||||||
|
else:
|
||||||
|
print(f"Failed to fetch weather for {station_name}: {response.status_code}")
|
||||||
|
|
||||||
|
def store_weather_data(weather, station_id):
|
||||||
|
"""Store weather data in the database."""
|
||||||
|
conn = get_db_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO weather_history (
|
||||||
|
weather_id, station_id, timestamp, temperature, precipitation,
|
||||||
|
wind_speed, wind_direction, humidity, pressure, visibility, weather_condition
|
||||||
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
str(uuid.uuid4()), station_id, datetime.now(), weather.get("main", {}).get("temp"),
|
||||||
|
weather.get("rain", {}).get("1h", 0), weather.get("wind", {}).get("speed"),
|
||||||
|
weather.get("wind", {}).get("deg"), weather.get("main", {}).get("humidity"),
|
||||||
|
weather.get("main", {}).get("pressure"), weather.get("visibility"),
|
||||||
|
weather.get("weather", [{}])[0].get("main")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# Schedule tasks
|
||||||
|
scheduler.add_job(fetch_train_schedules, 'interval', minutes=10)
|
||||||
|
scheduler.add_job(fetch_weather_data, 'interval', hours=1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
create_tables()
|
||||||
|
scheduler.start()
|
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
requests==2.31.0
|
||||||
|
psycopg2-binary==2.9.9
|
||||||
|
apscheduler==3.10.1
|
||||||
|
python-dotenv==1.0.0
|
Loading…
Reference in New Issue
Block a user