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