DWD-Stationsdaten importieren  (Gelesen 900 mal)

Offline falk

    • Wetterstation Scharnhausen
  • Registriert:
    15.04.2015, 07:28:04
  • Beiträge: 702
  • geogr. Position:
    48°42' 9°16'
  • Station:
    Davis Vantage Vue
DWD-Stationsdaten importieren
am: 28.01.2018, 11:45:41
Weil es ein wenig Fleißarbeit war möchte ich kurz dokumentieren, wie ich die Stationsdaten der DWD-Station Stuttgart-Echterdingen (04931) in MySQL importiere. Es lassen sich natürlich auch andere Stationsdaten einlesen. Hier sind nur Variablen anzupassen.

Ich benutze auf meinem Server die bestehende Datenbank weewx und habe diese durch die neue Tabelle dwd ergänzt:

create table dwd (
  dateTime    BIGINT PRIMARY KEY,

  -- tu
  pp          DECIMAL(5,1),        -- Luftdruck in Stationshoehe der voran. 10 min [hPa]
  p           DECIMAL(5,1),        -- auf NN reduzierter Luftdruck [hPa]
  tt          DECIMAL(4,1),        -- momentane Lufttemperatur in 2m Hoehe [Grad Celsius]
  td          DECIMAL(4,1),        -- Taupunkttemperatur in 2m Hoehe [Grad Celsius]
  rf          DECIMAL(3),          -- relative Feucht in 2m Hoehe [%]

  -- ff
  ff          DECIMAL(5,1),        -- Windgeschwindigkeitsmittel der voran. 10min [km/h]
  dd          DECIMAL(3),          -- Windrichtungsmittel der voran. 10min [Grad]

  -- fx
  fx          DECIMAL(5,1),        -- Maximum der Windgeschwindigkeit der voran. 10min [km/h]

  -- rr
  rws         DECIMAL(5,2),        -- Summe der Niederschlagsh. der vorangeg. 10Min [mm]

  -- sd
  sd          DECIMAL(2)           -- Sonnenscheindauer 10min [min]
);


Auf meinem Linux-Server habe ich ein Shell-Skript abgelegt, welches die Daten über OpenData holt und in die Datenbank schreibt.

Anzupassen sind hier die Variablen "station" und natürlich "db_cmd" mit eigenen Zugangsdaten. Das Verzeichnis "observations-germany" sollte existieren.

#!/bin/sh

station=04931
db_cmd="mysql -N -u DB_USER --password=DB_PASSWORD weewx"

# get recent tu-data
min_date=`echo "select max(dateTime) from dwd where tt is not null;" | ${db_cmd}`
zip_file=10minutenwerte_TU_${station}_akt.zip

wget ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/10_minutes/air_temperature/recent/${zip_file} -O observations-germany/${zip_file}
unzip -p observations-germany/${zip_file} | ./import_data.py ${min_date} | ${db_cmd}

# get recent ff-data
min_date=`echo "select max(dateTime) from dwd where ff is not null;" | ${db_cmd}`
zip_file=10minutenwerte_wind_${station}_akt.zip

wget ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/10_minutes/wind/recent/${zip_file} -O observations-germany/${zip_file}
unzip -p observations-germany/${zip_file} | ./import_data.py ${min_date} | ${db_cmd}

# get recent fx-data
min_date=`echo "select max(dateTime) from dwd where fx is not null;" | ${db_cmd}`
zip_file=10minutenwerte_extrema_wind_${station}_akt.zip

wget ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/10_minutes/extreme_wind/recent/${zip_file} -O observations-germany/${zip_file}
unzip -p observations-germany/${zip_file} | ./import_data.py ${min_date} | ${db_cmd}

# get recent rr-data
min_date=`echo "select max(dateTime) from dwd where rws is not null;" | ${db_cmd}`
zip_file=10minutenwerte_nieder_${station}_akt.zip

wget ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/10_minutes/precipitation/recent/${zip_file} -O observations-germany/${zip_file}
unzip -p observations-germany/${zip_file} | ./import_data.py ${min_date} | ${db_cmd}

# get recent sd-data
min_date=`echo "select max(dateTime) from dwd where sd is not null;" | ${db_cmd}`
zip_file=10minutenwerte_SOLAR_${station}_akt.zip

wget ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/10_minutes/solar/recent/${zip_file} -O observations-germany/${zip_file}
unzip -p observations-germany/${zip_file} | ./import_data.py ${min_date} | ${db_cmd}

Das Python-Skript "import_data.py" liest die DWD-Daten über die Standard-Eingabe und konvertiert nach SQL.

Hier ist anzupassen:
min_time (Unix-Zeitstempel. Mich interessieren nur Daten ab 2015)
my_id: Wieder die Stationsid, diesmal numerisch
height: Der Höhenwert für die Reduktionsberechnung auf Meereshöhe (QFF)

#!/usr/bin/python
'''
Created on 19.01.2018

'''
import calendar
import datetime
import math
import sys

min_time = 1420066800
my_id = 4931
height = 392.0

def reduction(height, pressure, temperature, humidity):
    e = 6.112 * math.exp(17.62 * temperature / (243.12 + temperature)) * humidity / 100.0
    var1 = height * 9.80665 / 287.05
    var2 = 273.15 + temperature + e * 0.12 + 0.0065 * height / 2
    return pressure * math.exp(var1 / var2)

def to_timestamp(date):
    return calendar.timegm(datetime.datetime.strptime(date, "%Y%m%d%H%M").timetuple())

# stations_id;mess_datum;  qn;pp_10;tt_10;tm5_10;rf_10;td_10;eor
def parse_tu(content):
    if len(content) < 8:
        return

    stations_id = int(content[0])
    timestamp = to_timestamp(content[1])
    if stations_id != my_id or timestamp < min_time:
        return

    qn          = int(content[2])
    pp_10       = float(content[3])
    tt_10       = float(content[4])
    tm5_10      = content[5]
    rf_10       = float(content[6])
    td_10       = float(content[7])

    p = round(reduction(height, pp_10, tt_10, rf_10), 1)

    sql = "INSERT INTO dwd (dateTime, pp, p, tt, td, rf) VALUES(%d, %.1f, %.1f, %.1f, %.1f, %d) ON DUPLICATE KEY UPDATE pp=%.1f, p=%.1f, tt=%.1f, td=%.1f, rf=%d;" % (timestamp, pp_10, p, tt_10, td_10, rf_10, pp_10, p, tt_10, td_10, rf_10)
    print(sql)

# stations_id;mess_datum;  qn;ff_10;dd_10;eor
def parse_ff(content):
    if len(content) < 5:
        return

    stations_id = int(content[0])
    timestamp = to_timestamp(content[1])
    if stations_id != my_id or timestamp < min_time:
        return

    qn          = int(content[2])
    ff_10       = round(float(content[3]) * 3.6, 0)
    dd_10       = int(content[4])

    sql = "INSERT INTO dwd (dateTime, ff, dd) VALUES(%d, %d, %d) ON DUPLICATE KEY UPDATE ff=%d, dd=%d;" % (timestamp, ff_10, dd_10, ff_10, dd_10)
    print(sql)

# stations_id;mess_datum;  qn;fx_10;fnx_10;fmx_10;dx_10;eor
def parse_fx(content):
    if len(content) < 7:
        return

    stations_id = int(content[0])
    timestamp = to_timestamp(content[1])
    if stations_id != my_id or timestamp < min_time:
        return

    qn          = int(content[2])
    fx_10       = round(float(content[3]) * 3.6, 0)
    fnx_10      = round(float(content[4]) * 3.6, 0)
    fmx_10      = round(float(content[5]) * 3.6, 0)
    dx_10       = int(content[6])

    sql = "INSERT INTO dwd (dateTime, fx) VALUES(%d, %d) ON DUPLICATE KEY UPDATE fx=%d;" % (timestamp, fx_10, fx_10)
    print(sql)

# stations_id;mess_datum;  qn;rws_dau_10;rws_10;rws_ind_10;eor
def parse_rr(content):
    if len(content) < 6:
        return

    stations_id = int(content[0])
    timestamp = to_timestamp(content[1])
    if stations_id != my_id or timestamp < min_time:
        return

    qn          = int(content[2])
    rws_dau_10  = int(content[3])
    rws_10      = float(content[4])
    rws_ind_10  = int(content[5])

    sql = "INSERT INTO dwd (dateTime, rws) VALUES(%d, %.2f) ON DUPLICATE KEY UPDATE rws=%.2f;" % (timestamp, rws_10, rws_10)
    print(sql)

# stations_id;mess_datum;  qn;ds_10;gs_10;sd_10;ls_10;eor
def parse_sd(content):
    if len(content) < 7:
        return

    stations_id = int(content[0])
    timestamp = to_timestamp(content[1])
    if stations_id != my_id or timestamp < min_time:
        return

    qn          = int(content[2])
    ds_10       = int(content[3])
    gs_10       = int(content[4])
    sd_10       = 0 if '-999' in content[5] else round(float(content[5]) * 60, 0)
    ls_10       = int(content[6])

    sql = "INSERT INTO dwd (dateTime, sd) VALUES(%d, %d) ON DUPLICATE KEY UPDATE sd=%d;" % (timestamp, sd_10, sd_10)
    print(sql)

if len(sys.argv) > 1:
    min_time = int(sys.argv[1])

header = sys.stdin.readline()
for line in sys.stdin:
    if 'SD_10' in header:
        parse_sd(line.split(';'))
    elif '-999' in line:
        continue
    elif 'TT_10' in header:
        parse_tu(line.split(';'))
    elif 'FF_10' in header:
        parse_ff(line.split(';'))
    elif 'FX_10' in header:
        parse_fx(line.split(';'))
    elif 'RWS_10' in header:
        parse_rr(line.split(';'))


Bisher nutze ich die Daten für meine Heatmaps https://buwx.de/index.php/chart/heatmaps und zur Kontrolle der Messwerte für Luftdruck und Niederschlag.

Initial habe ich die Tabelle mit den historischen Daten gefüllt. Diese findet man unter dem Verzeichnis "historical". Da die Recent-Daten erst einige Stunden nach Mitternacht aktualisiert werden, habe ich einen Cron-Job für 4 Uhr nachts eingerichtet.

Für Hinweise auf Fehler bin ich natürlich sehr dankbar.

Wetterstationen.info Forum

DWD-Stationsdaten importieren
« am: 28.01.2018, 11:45:41 »

Offline wneudeck

  • Administrator
    • Werner Neudecks Wetterpage
    • Männlich
  • Registriert:
    19.04.2002, 02:00:00
  • Beiträge: 13.270
  • Ort:
    Donauwörth
  • Station:
    Davis Vantage Pro 2
Re: DWD-Stationsdaten importieren
Antwort #1 am: 28.01.2018, 19:29:42
Halo falk,
danke, habe das Thema mal angepinnt, damit es, zumindest vorläufig mal, leichter auffindbar ist.