Mapping der neu gesendeten Werte auf die in der DB (main.py)
Anzeige der letzten 24h richtig (App.jsx) Y-Bereichsberechnung für alle 3 (THP) dynamisch, Windbön mit angezeigt
This commit is contained in:
@@ -38,84 +38,116 @@ app = FastAPI(title="Weather Data Collector API")
|
||||
|
||||
# Pydantic Models
|
||||
class WeatherDataInput(BaseModel):
|
||||
# Unterstütze beide Formate: datetime (String) oder dateTime (Unix-Timestamp)
|
||||
# Zeitstempel: ISO-String (time), datetime-String oder Unix-Timestamp
|
||||
time: str | None = None
|
||||
datetime: str | None = None
|
||||
dateTime: int | None = None
|
||||
|
||||
# Unterstütze beide Feldnamen
|
||||
|
||||
# Außentemperatur (Celsius): tempOut, temperature oder outTemp (Fahrenheit)
|
||||
tempOut: float | None = None # Celsius (neues Format)
|
||||
temperature: float | None = None
|
||||
outTemp: float | None = None # Fahrenheit
|
||||
|
||||
outTemp: float | None = None # Fahrenheit (altes Format)
|
||||
|
||||
# Innentemperatur
|
||||
tempIn: float | None = None # Celsius
|
||||
|
||||
# Außenfeuchte
|
||||
humOut: int | None = None
|
||||
humidity: int | None = None
|
||||
outHumidity: float | None = None
|
||||
|
||||
|
||||
# Innenfeuchte
|
||||
humIn: int | None = None
|
||||
|
||||
# Luftdruck
|
||||
pressure: float | None = None
|
||||
barometer: float | None = None # inHg
|
||||
|
||||
windSpeed: float | None = None # mph
|
||||
barTrend: int | None = None # hPa/Stunde
|
||||
|
||||
# Wind
|
||||
windAvg: float | None = None # m/s Durchschnitt (neues Format)
|
||||
windSpeed: float | None = None
|
||||
wind_speed: float | None = None
|
||||
|
||||
windGust: float | None = None # mph
|
||||
windGust: float | None = None
|
||||
wind_gust: float | None = None
|
||||
|
||||
windDir: float | None = None
|
||||
wind_dir: float | None = None
|
||||
|
||||
|
||||
# Niederschlag
|
||||
rain: float | None = None
|
||||
rainRate: float | None = None
|
||||
rain_rate: float | None = None
|
||||
|
||||
|
||||
# Vorhersage
|
||||
forecast: int | None = None
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
|
||||
def get_datetime_string(self) -> str:
|
||||
"""Konvertiere dateTime (Unix-Timestamp) zu datetime (String)"""
|
||||
if self.datetime:
|
||||
"""Zeitstempel als String zurückgeben"""
|
||||
if self.time:
|
||||
return self.time
|
||||
elif self.datetime:
|
||||
return self.datetime
|
||||
elif self.dateTime:
|
||||
from datetime import datetime as dt
|
||||
return dt.fromtimestamp(self.dateTime).strftime('%Y-%m-%d %H:%M:%S')
|
||||
raise ValueError("Weder datetime noch dateTime vorhanden")
|
||||
|
||||
raise ValueError("Kein Zeitstempel vorhanden (time, datetime oder dateTime)")
|
||||
|
||||
def get_temperature_celsius(self) -> float | None:
|
||||
"""Konvertiere Temperatur von Fahrenheit zu Celsius falls nötig"""
|
||||
if self.temperature is not None:
|
||||
"""Außentemperatur in Celsius"""
|
||||
if self.tempOut is not None:
|
||||
return self.tempOut
|
||||
elif self.temperature is not None:
|
||||
return self.temperature
|
||||
elif self.outTemp is not None:
|
||||
# Fahrenheit zu Celsius: (F - 32) * 5/9
|
||||
return (self.outTemp - 32) * 5 / 9
|
||||
return None
|
||||
|
||||
|
||||
def get_temp_in(self) -> float | None:
|
||||
"""Innentemperatur in Celsius"""
|
||||
return self.tempIn
|
||||
|
||||
def get_humidity_int(self) -> int | None:
|
||||
"""Hole Humidity-Wert"""
|
||||
if self.humidity is not None:
|
||||
"""Außenfeuchte"""
|
||||
if self.humOut is not None:
|
||||
return int(self.humOut)
|
||||
elif self.humidity is not None:
|
||||
return int(self.humidity)
|
||||
elif self.outHumidity is not None:
|
||||
return int(self.outHumidity)
|
||||
return None
|
||||
|
||||
|
||||
def get_humidity_in(self) -> int | None:
|
||||
"""Innenfeuchte"""
|
||||
return int(self.humIn) if self.humIn is not None else None
|
||||
|
||||
def get_pressure_hpa(self) -> float | None:
|
||||
"""Konvertiere Druck von inHg zu hPa falls nötig"""
|
||||
"""Luftdruck in hPa"""
|
||||
if self.pressure is not None:
|
||||
return self.pressure
|
||||
elif self.barometer is not None:
|
||||
# inHg zu hPa: inHg * 33.8639
|
||||
return self.barometer * 33.8639
|
||||
return None
|
||||
|
||||
|
||||
def get_wind_speed(self) -> float | None:
|
||||
"""Hole Windgeschwindigkeit"""
|
||||
return self.windSpeed if self.windSpeed is not None else self.wind_speed
|
||||
|
||||
"""Durchschnittliche Windgeschwindigkeit"""
|
||||
if self.windAvg is not None:
|
||||
return self.windAvg
|
||||
elif self.windSpeed is not None:
|
||||
return self.windSpeed
|
||||
return self.wind_speed
|
||||
|
||||
def get_wind_gust(self) -> float | None:
|
||||
"""Hole Windböen"""
|
||||
"""Windböe"""
|
||||
return self.windGust if self.windGust is not None else self.wind_gust
|
||||
|
||||
|
||||
def get_wind_dir(self) -> float | None:
|
||||
"""Hole Windrichtung"""
|
||||
"""Windrichtung"""
|
||||
return self.windDir if self.windDir is not None else self.wind_dir
|
||||
|
||||
|
||||
def get_rain_rate(self) -> float | None:
|
||||
"""Hole Regenrate"""
|
||||
"""Regenrate"""
|
||||
return self.rainRate if self.rainRate is not None else self.rain_rate
|
||||
|
||||
|
||||
@@ -137,7 +169,7 @@ def get_db_connection():
|
||||
|
||||
|
||||
def setup_database():
|
||||
"""Tabelle erstellen falls nicht vorhanden"""
|
||||
"""Tabelle erstellen und fehlende Spalten ergänzen"""
|
||||
try:
|
||||
conn = get_db_connection()
|
||||
with conn.cursor() as cursor:
|
||||
@@ -157,8 +189,13 @@ def setup_database():
|
||||
UNIQUE(datetime)
|
||||
)
|
||||
""")
|
||||
# Neue Spalten ergänzen (idempotent)
|
||||
cursor.execute("ALTER TABLE weather_data ADD COLUMN IF NOT EXISTS temp_in FLOAT")
|
||||
cursor.execute("ALTER TABLE weather_data ADD COLUMN IF NOT EXISTS humidity_in INTEGER")
|
||||
cursor.execute("ALTER TABLE weather_data ADD COLUMN IF NOT EXISTS forecast INTEGER")
|
||||
cursor.execute("ALTER TABLE weather_data ADD COLUMN IF NOT EXISTS bar_trend INTEGER")
|
||||
conn.commit()
|
||||
logger.info("Tabelle weather_data bereit")
|
||||
logger.info("Tabelle weather_data bereit (inkl. neuer Spalten)")
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler bei Datenbanksetup: {e}")
|
||||
@@ -238,41 +275,59 @@ async def receive_weather_data(data: WeatherDataInput):
|
||||
# Konvertiere zu den richtigen Werten
|
||||
dt_string = data.get_datetime_string()
|
||||
temp_c = data.get_temperature_celsius()
|
||||
temp_in = data.get_temp_in()
|
||||
humidity = data.get_humidity_int()
|
||||
humidity_in = data.get_humidity_in()
|
||||
pressure = data.get_pressure_hpa()
|
||||
bar_trend = data.barTrend
|
||||
wind_speed = data.get_wind_speed()
|
||||
wind_gust = data.get_wind_gust()
|
||||
wind_dir = data.get_wind_dir()
|
||||
rain = data.rain
|
||||
rain_rate = data.get_rain_rate()
|
||||
|
||||
logger.info(f"Konvertierte Daten - datetime: {dt_string}, temp: {temp_c}°C, humidity: {humidity}%, pressure: {pressure} hPa")
|
||||
|
||||
forecast = data.forecast
|
||||
|
||||
logger.info(
|
||||
f"Konvertierte Daten - datetime: {dt_string}, "
|
||||
f"tempOut: {temp_c}°C, tempIn: {temp_in}°C, "
|
||||
f"humOut: {humidity}%, humIn: {humidity_in}%, "
|
||||
f"pressure: {pressure} hPa, barTrend: {bar_trend}"
|
||||
)
|
||||
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute("""
|
||||
INSERT INTO weather_data
|
||||
(datetime, temperature, humidity, pressure, wind_speed,
|
||||
wind_gust, wind_dir, rain, rain_rate)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
INSERT INTO weather_data
|
||||
(datetime, temperature, temp_in, humidity, humidity_in,
|
||||
pressure, bar_trend, wind_speed, wind_gust, wind_dir,
|
||||
rain, rain_rate, forecast)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
ON CONFLICT (datetime) DO UPDATE SET
|
||||
temperature = EXCLUDED.temperature,
|
||||
temp_in = EXCLUDED.temp_in,
|
||||
humidity = EXCLUDED.humidity,
|
||||
humidity_in = EXCLUDED.humidity_in,
|
||||
pressure = EXCLUDED.pressure,
|
||||
bar_trend = EXCLUDED.bar_trend,
|
||||
wind_speed = EXCLUDED.wind_speed,
|
||||
wind_gust = EXCLUDED.wind_gust,
|
||||
wind_dir = EXCLUDED.wind_dir,
|
||||
rain = EXCLUDED.rain,
|
||||
rain_rate = EXCLUDED.rain_rate
|
||||
rain_rate = EXCLUDED.rain_rate,
|
||||
forecast = EXCLUDED.forecast
|
||||
""", (
|
||||
dt_string,
|
||||
temp_c,
|
||||
temp_in,
|
||||
humidity,
|
||||
humidity_in,
|
||||
pressure,
|
||||
bar_trend,
|
||||
wind_speed,
|
||||
wind_gust,
|
||||
wind_dir,
|
||||
rain,
|
||||
rain_rate
|
||||
rain_rate,
|
||||
forecast
|
||||
))
|
||||
conn.commit()
|
||||
logger.info(f"Daten gespeichert für {dt_string} (UTC)")
|
||||
|
||||
Reference in New Issue
Block a user