#!/usr/bin/python3 import datetime import os import sys import time import toml from psutil import process_iter import eigene_wetterdaten import messwerte_umrechner as mwu import weewx_db_model as db_weewx import setup_logging import db_postgrest def config_laden(): configfile = os.path.join(SKRIPTPFAD, "wetterconfig.toml") with open(configfile) as file: return toml.loads(file.read()) SKRIPTPFAD = os.path.abspath(os.path.dirname(__file__)) CONFIG = config_laden() LOGGER = setup_logging.create_logger("grafana_export", CONFIG["loglevel"]) SENDELIMIT = 1000 def check_process(): processliste = [p.cmdline() for p in process_iter() if "python" in p.name()] return sum([p.count(sys.argv[0]) for p in processliste]) def rohdaten_laden(timestamp, stationsname): aufruf_wiederholen = False LOGGER.debug("Lese WeeWx Datenbank") query = db_weewx.Archive.select().where(db_weewx.Archive.date_time > timestamp)\ .order_by(db_weewx.Archive.date_time.asc()).limit(int(SENDELIMIT * 1.5)) gesamtzahl = (len(query)) if gesamtzahl > SENDELIMIT: gesamtzahl = SENDELIMIT LOGGER.info(f"Gesamtanzahl an Datensätze: {gesamtzahl} wird geladen") basiswetterdaten_liste = [] zusatzwetterdaten_liste = [] for nr, datensatz in enumerate(query): LOGGER.debug(f"Datensatz {nr + 1} von {gesamtzahl}") rohdaten = {"ts": datensatz.date_time} if datensatz.us_units == 1: rohdaten["outtemp"] = mwu.temperaturumrechner(datensatz.out_temp) rohdaten["inTemp"] = mwu.temperaturumrechner(datensatz.in_temp) rohdaten["luftdruck"] = mwu.druckumrechner(datensatz.barometer) rohdaten["wind"] = mwu.windumrechner(datensatz.wind_speed) rohdaten["windboe"] = mwu.windumrechner(datensatz.wind_gust) rohdaten["regenrate"] = mwu.regen_rate(datensatz.rain_rate) rohdaten["regenaktuell"] = mwu.regen_menge(datensatz.rain) rohdaten["taupunkt"] = mwu.temperaturumrechner(datensatz.dewpoint) rohdaten["heatindex"] = mwu.temperaturumrechner(datensatz.heatindex) rohdaten["windchill"] = mwu.temperaturumrechner(datensatz.windchill) else: rohdaten["outtemp"] = datensatz.out_temp rohdaten["inTemp"] = datensatz.in_temp rohdaten["luftdruck"] = datensatz.barometer rohdaten["wind"] = datensatz.wind_speed rohdaten["windboe"] = datensatz.wind_gust rohdaten["regenrate"] = datensatz.rain_rate rohdaten["regenaktuell"] = datensatz.rain rohdaten["taupunkt"] = datensatz.dewpoint rohdaten["heatindex"] = datensatz.heatindex rohdaten["wincchill"] = datensatz.windchill if isinstance(datensatz.out_humidity, (int, float)): rohdaten["outluftfeuchte"] = float(round(datensatz.out_humidity, 0)) else: rohdaten["outluftfeuchte"] = None if isinstance(datensatz.in_humidity, (int, float)): rohdaten["inLuftfeuchte"] = float(round(datensatz.in_humidity, 0)) else: rohdaten["inLuftfeuchte"] = None if isinstance(datensatz.wind_dir, (int, float)): rohdaten["windrichtung_grad"] = float(round(datensatz.wind_dir, 1)) else: rohdaten["windrichtung_grad"] = None if isinstance(datensatz.wind_gust_dir, (int, float)): rohdaten["windboe_richtung"] = float(round(datensatz.wind_gust_dir, 1)) else: rohdaten["windboe_richtung"] = None rohdaten["windrichtung"] = mwu.himmelsrichtungwandler(datensatz.wind_dir) rohdaten["out_abs_luftfeuchte"] = mwu.absolute_luftfeuchtigkeit(rohdaten["outtemp"], rohdaten["outluftfeuchte"]) rohdaten = eigene_wetterdaten.eigene_wetterdaten(rohdaten) basiswetterdaten_liste.append( db_postgrest.Basiswetterdaten(stationsname=stationsname, **{key: value for key, value in rohdaten.items() if key in db_postgrest.Basiswetterdaten.__dataclass_fields__})) zusatzdatenliste = [{key: value} for key, value in rohdaten.items() if key not in db_postgrest.Basiswetterdaten.__dataclass_fields__] for zusatzdaten in zusatzdatenliste: for key, value in zusatzdaten.items(): if key is None or value is None: continue zusatzwetterdaten_liste.append( db_postgrest.Zusatzwetterdaten(ts=rohdaten["ts"], stationsname=stationsname, wertname=key, wert=value, public=False)) if nr >= SENDELIMIT - 1: aufruf_wiederholen = True break return basiswetterdaten_liste, zusatzwetterdaten_liste, aufruf_wiederholen def freigabe_setzen(zusatzwetterdaten_liste): for zusatzdaten in zusatzwetterdaten_liste: if zusatzdaten.wertname in CONFIG["grafana"]["public"]: zusatzdaten.public = CONFIG["grafana"]["public"][zusatzdaten.wertname] else: zusatzdaten.public = False return zusatzwetterdaten_liste def main(): laufende_prozesse = check_process() if laufende_prozesse > 1: print("EXIT aufgrund laufender Prozesse") sys.exit() # Verzögerung aufgrund vom Cronjob, >>alle 5Minute, damit es nicht mit der Erstellung von Weewx kolidiert time.sleep(CONFIG["weewx"]["sleeptime"]) db_adapter = CONFIG["weewx"]["db"] db = db_weewx.init_db(CONFIG["weewx"][db_adapter]["database"], db_adapter, CONFIG["weewx"].get(db_adapter)) db_weewx.database.initialize(db) headers = {f"Authorization": "{user} {token}".format(user=CONFIG["zieldb"]["postgrest"]["user"], token=CONFIG["zieldb"]["postgrest"]["token"])} url = CONFIG["zieldb"]["postgrest"]["url"] if not url.endswith("/"): url = f"{url}/" while True: letzter_ts_server = db_postgrest.hole_letzten_ts(url, CONFIG["zieldb"]["postgrest"]["tablename_basiswetterdaten"], headers, CONFIG["grafana"]["grafana_name"]) basiswetterdaten, zusatzwetterdaten, aufruf_wiederholen = rohdaten_laden(letzter_ts_server.timestamp(), CONFIG["grafana"]["grafana_name"]) zusatzwetterdaten = freigabe_setzen(zusatzwetterdaten) db_postgrest.sende_daten(url, CONFIG["zieldb"]["postgrest"]["tablename_basiswetterdaten"], headers, basiswetterdaten, LOGGER) db_postgrest.sende_daten(url, CONFIG["zieldb"]["postgrest"]["tablename_zusatzwetterdaten"], headers, zusatzwetterdaten, LOGGER) if not aufruf_wiederholen: break if __name__ == "__main__": start = datetime.datetime.now() LOGGER.debug(f"Start: {start}") try: main() except KeyboardInterrupt: LOGGER.info("Durch Benutzer abgebrochen") else: LOGGER.info("Export erfolgreich") ende = datetime.datetime.now() LOGGER.debug(f"Ende: {ende}") LOGGER.debug(f"Dauer: {ende - start}")