diff --git a/db_addon/__init__.py b/db_addon/__init__.py index ebdb2d76e..c77335857 100644 --- a/db_addon/__init__.py +++ b/db_addon/__init__.py @@ -34,7 +34,7 @@ import pickle import operator from dateutil.relativedelta import relativedelta -from typing import Union +from typing import Union, List, Dict from dataclasses import dataclass, InitVar from collections import deque @@ -44,7 +44,6 @@ from lib.shtime import Shtime from lib.plugin import Plugins from .webif import WebInterface -from .item_attributes import * from .item_attributes_master import ITEM_ATTRIBUTES import lib.db @@ -60,7 +59,7 @@ class DatabaseAddOn(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the items """ - PLUGIN_VERSION = '1.2.9' + PLUGIN_VERSION = '1.2.10' def __init__(self, sh): """ @@ -70,7 +69,7 @@ def __init__(self, sh): # Call init code of parent class (SmartPlugin) super().__init__() - self.logger.debug(f'Start of {self.get_shortname()} Plugin.') + self.logger.debug(f'Start of {self.get_fullname()} Plugin.') # get item and shtime instance self.shtime = Shtime.get_instance() @@ -82,7 +81,7 @@ def __init__(self, sh): self.current_values = {} # Dict to hold min and max value of current day / week / month / year for items self.previous_values = {} # Dict to hold value of end of last day / week / month / year for items self.item_cache = {} # Dict to hold item_id, oldest_log_ts and oldest_entry for items - self.value_list_raw_data = {} # List to hold raw data + self.value_list_raw_data = {} # Dict to hold value list raw data # define variables for database, database connection, working queue and status self.item_queue = queue.Queue() # Queue containing all to be executed items @@ -104,6 +103,7 @@ def __init__(self, sh): self.default_net_read_timeout = 60 # define variables from plugin parameters + self._pause_item_path = self.get_parameter_value('pause_item') self.db_configname = self.get_parameter_value('database_plugin_config') self.startup_run_delay = self.get_parameter_value('startup_run_delay') self.ignore_0 = self.get_parameter_value('ignore_0') @@ -114,7 +114,7 @@ def __init__(self, sh): # path and filename for data storage data_storage_file = 'db_addon_data' - self.data_storage_path = f"{os.getcwd()}/var/plugin_data/{self.get_shortname()}/{data_storage_file}.pkl" + self.data_storage_path = f"{os.getcwd()}/var/plugin_data/{self.get_fullname()}/{data_storage_file}.pkl" # get debug log options self.debug_log = DebugLogOptions(self.log_level) @@ -130,24 +130,24 @@ def run(self): Run method for the plugin """ - self.logger.debug("Run method called") + self.logger.dbghigh(self.translate("Methode '{method}' aufgerufen", {'method': 'run()'})) # check existence of db-plugin, get parameters, and init connection to db if not self._check_db_existence(): self.logger.error(f"Check of existence of database plugin incl connection check failed. Plugin not loaded") - return + return self.deinit() # create db object self._db = lib.db.Database("DatabaseAddOn", self.db_driver, self.connection_data) if not self._db.api_initialized: self.logger.error("Initialization of database API failed") - return + return self.deinit() self.logger.debug("Initialization of database API successful") # check initialization of db if not self._initialize_db(): self.logger.error("Connection to database failed") - return + return self.deinit() self._db.close() # check db connection settings @@ -168,6 +168,10 @@ def run(self): # create list if all relevant database items self._create_list_of_relevant_database_items() + # let the plugin change the state of pause_item + if self._pause_item: + self._pause_item(False, self.get_fullname()) + # set plugin to alive self.alive = True @@ -179,12 +183,25 @@ def stop(self): Stop method for the plugin """ - self.logger.debug("Stop method called") + self.logger.dbghigh(self.translate("Methode '{method}' aufgerufen", {'method': 'stop()'})) + + # set plugin to alive self.alive = False - self.scheduler_remove('cyclic') - self.scheduler_remove('onchange_delay') + + # let the plugin change the state of pause_item + if self._pause_item: + self._pause_item(True, self.get_fullname()) + + # this stops all schedulers the plugin has started. + # self.scheduler_remove('cyclic') + # self.scheduler_remove('onchange_delay') + self.scheduler_remove_all() + + # close db object if self._db: self._db.close() + + # save cache data self.save_cache_data() def parse_item(self, item: Item): @@ -206,269 +223,252 @@ def get_query_parameters_from_db_addon_fct() -> Union[dict, None]: # get parameter db_addon_fct_vars = db_addon_fct.split('_') - func = timeframe = timedelta = start = end = group = group2 = data_con_func = log_text = None - required_params = None - - if db_addon_fct in HISTORIE_ATTRIBUTES_ONCHANGE: - # handle functions 'minmax onchange' in format 'minmax_timeframe_func' items like 'minmax_heute_max', 'minmax_heute_min', 'minmax_woche_max', 'minmax_woche_min' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - func = db_addon_fct_vars[2] if db_addon_fct_vars[2] in ALLOWED_MINMAX_FUNCS else None - start = end = 0 - log_text = 'minmax_timeframe_func' - required_params = [func, timeframe, start, end] - - elif db_addon_fct in HISTORIE_ATTRIBUTES_LAST: - # handle functions 'minmax_last' in format 'minmax_last_timedelta|timeframe_function' like 'minmax_last_24h_max' - func = db_addon_fct_vars[3] - start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[2]) - start = to_int(start) - timeframe = translate_timeframe(timeframe) - end = 0 - log_text = 'minmax_last_timedelta|timeframe_function' - required_params = [func, timeframe, start, end] - - elif db_addon_fct in HISTORIE_ATTRIBUTES_TIMEFRAME: - # handle functions 'min/max/avg' in format 'minmax_timeframe_timedelta_func' like 'minmax_heute_minus2_max' - func = db_addon_fct_vars[3] # min, max, avg - timeframe = translate_timeframe(db_addon_fct_vars[1]) # day, week, month, year - start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) - log_text = 'minmax_timeframe_timedelta_func' - required_params = [func, timeframe, start, end] - - elif db_addon_fct in ZAEHLERSTAND_ATTRIBUTES_TIMEFRAME: - # handle functions 'zaehlerstand' in format 'zaehlerstand_timeframe_timedelta' like 'zaehlerstand_heute_minus1' - func = 'last' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) - log_text = 'zaehlerstand_timeframe_timedelta' - required_params = [timeframe, start, end] - - elif db_addon_fct in VERBRAUCH_ATTRIBUTES_ONCHANGE: - # handle functions 'verbrauch onchange' items in format 'verbrauch_timeframe' like 'verbrauch_heute', 'verbrauch_woche', 'verbrauch_monat', 'verbrauch_jahr' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - start = end = 0 - log_text = 'verbrauch_timeframe' - required_params = [timeframe, start, end] - - elif db_addon_fct in VERBRAUCH_ATTRIBUTES_TIMEFRAME: - # handle functions 'verbrauch on-demand' in format 'verbrauch_timeframe_timedelta' like 'verbrauch_heute_minus2' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) - log_text = 'verbrauch_timeframe_timedelta' - required_params = [timeframe, start, end] - - elif db_addon_fct in VERBRAUCH_ATTRIBUTES_LAST: - # handle functions 'verbrauch_last' in format 'verbrauch_last_timedelta|timeframe' like 'verbrauch_last_24h' - start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[2]) - start = to_int(start) - timeframe = translate_timeframe(timeframe) - end = 0 - log_text = 'verbrauch_last_timedelta|timeframe' - required_params = [timeframe, start, end] - - elif db_addon_fct in VERBRAUCH_ATTRIBUTES_ROLLING: - # handle functions 'verbrauch_on-demand' in format 'verbrauch_rolling_window_timeframe_timedelta' like 'verbrauch_rolling_12m_woche_minus1' - func = db_addon_fct_vars[1] - window_inc, window_dur = split_sting_letters_numbers(db_addon_fct_vars[2]) - window_inc = to_int(window_inc) # 12 - window_dur = translate_timeframe(window_dur) # day, week, month, year - timeframe = translate_timeframe(db_addon_fct_vars[3]) # day, week, month, year - end = to_int(split_sting_letters_numbers(db_addon_fct_vars[4])[1]) - if window_dur in ALLOWED_QUERY_TIMEFRAMES and window_inc and timeframe and end: - start = to_int(timeframe_to_timeframe(timeframe, window_dur) * window_inc) + end - log_text = 'verbrauch_rolling_window_timeframe_timedelta' - required_params = [func, timeframe, start, end] - - elif db_addon_fct in VERBRAUCH_ATTRIBUTES_JAHRESZEITRAUM: - # handle functions of format 'verbrauch_jahreszeitraum_timedelta' like 'verbrauch_jahreszeitraum_minus1' - timeframe = translate_timeframe(db_addon_fct_vars[1]) # day, week, month, year - timedelta = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) - log_text = 'verbrauch_jahreszeitraum_timedelta' - required_params = [timeframe, timedelta] - - elif db_addon_fct in TAGESMITTEL_ATTRIBUTES_ONCHANGE: - # handle functions 'tagesmitteltemperatur onchange' items in format 'tagesmitteltemperatur_timeframe' like 'tagesmitteltemperatur_heute', 'tagesmitteltemperatur_woche', 'tagesmitteltemperatur_monat', 'tagesmitteltemperatur_jahr' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - func = 'max' - start = end = 0 - log_text = 'tagesmitteltemperatur_timeframe' - required_params = [timeframe, start, end] - - elif db_addon_fct in TAGESMITTEL_ATTRIBUTES_TIMEFRAME: - # handle 'tagesmitteltemperatur_timeframe_timedelta' like 'tagesmitteltemperatur_heute_minus1' - func = 'max' - timeframe = translate_timeframe(db_addon_fct_vars[1]) - start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) - data_con_func = 'first_hour_avg_day' - log_text = 'tagesmitteltemperatur_timeframe_timedelta' - required_params = [func, timeframe, start, end, data_con_func] - - elif db_addon_fct in SERIE_ATTRIBUTES_MINMAX: - # handle functions 'serie_minmax' in format 'serie_minmax_timeframe_func_start|group' like 'serie_minmax_monat_min_15m' - func = db_addon_fct_vars[3] - timeframe = translate_timeframe(db_addon_fct_vars[2]) - start, group = split_sting_letters_numbers(db_addon_fct_vars[4]) - start = to_int(start) - group = translate_timeframe(group) - end = 0 - log_text = 'serie_minmax_timeframe_func_start|group' - required_params = [func, timeframe, start, end, group] - - elif db_addon_fct in SERIE_ATTRIBUTES_ZAEHLERSTAND: - # handle functions 'serie_zaehlerstand' in format 'serie_zaehlerstand_timeframe_start|group' like 'serie_zaehlerstand_tag_30d' - timeframe = translate_timeframe(db_addon_fct_vars[2]) - start, group = split_sting_letters_numbers(db_addon_fct_vars[3]) - start = to_int(start) - group = translate_timeframe(group) - log_text = 'serie_zaehlerstand_timeframe_start|group' - required_params = [timeframe, start, group] - - elif db_addon_fct in SERIE_ATTRIBUTES_VERBRAUCH: - # handle all functions of format 'serie_verbrauch_timeframe_start|group' like 'serie_verbrauch_tag_30d' - timeframe = translate_timeframe(db_addon_fct_vars[2]) - start, group = split_sting_letters_numbers(db_addon_fct_vars[3]) - start = to_int(start) - group = translate_timeframe(group) - log_text = 'serie_verbrauch_timeframe_start|group' - required_params = [timeframe, start, group] - - elif db_addon_fct in SERIE_ATTRIBUTES_SUMME: - # handle all summe in format 'serie_xxsumme_timeframe_count|group' like serie_waermesumme_monat_24m - func = 'sum_max' - start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[3]) - start = to_int(start) - timeframe = translate_timeframe(timeframe) - end = 0 - group = 'day', - group2 = 'month' - log_text = 'serie_xxsumme_timeframe_count|group' - required_params = [func, timeframe, start, end, group, group2] - - elif db_addon_fct in SERIE_ATTRIBUTES_MITTEL_D: - # handle 'serie_tagesmittelwert_count|group' like 'serie_tagesmittelwert_0d' => Tagesmittelwert der letzten 0 Tage (also heute) - func = 'max' - timeframe = 'year' - start, group = split_sting_letters_numbers(db_addon_fct_vars[2]) - start = to_int(start) - group = translate_timeframe(group) - end = 0 - log_text = 'serie_tagesmittelwert_count|group' - required_params = [func, timeframe, start, end, group] - - elif db_addon_fct in SERIE_ATTRIBUTES_MITTEL_H: - # handle 'serie_tagesmittelwert_group2_count|group' like 'serie_tagesmittelwert_stunde_0d' => Stundenmittelwerte der letzten 0 Tage (also heute) - func = 'avg1' - timeframe = 'day' - end = 0 - group = 'hour' - start, group2 = split_sting_letters_numbers(db_addon_fct_vars[3]) - start = to_int(start) - group2 = translate_timeframe(group2) - log_text = 'serie_tagesmittelwert_group2_count|group' - required_params = [func, timeframe, start, end, group, group2] - - elif db_addon_fct in SERIE_ATTRIBUTES_MITTEL_H1: - # handle 'serie_tagesmittelwert_stunde_start_end|group' like 'serie_tagesmittelwert_stunde_30_0d' => Stundenmittelwerte von vor 30 Tagen bis vor 0 Tagen (also heute) - data_con_func = 'avg_hour' - start = to_int(db_addon_fct_vars[3]) - end, timeframe = split_sting_letters_numbers(db_addon_fct_vars[4]) - end = to_int(end) - timeframe = translate_timeframe(timeframe) - log_text = 'serie_tagesmittelwert_stunde_start_end|group' - required_params = [timeframe, data_con_func, start, end] - - elif db_addon_fct in SERIE_ATTRIBUTES_MITTEL_D_H: - # handle 'serie_tagesmittelwert_tag_stunde_end|group' like 'serie_tagesmittelwert_tag_stunde_30d' => Tagesmittelwert auf Basis des Mittelwerts pro Stunden für die letzten 30 Tage - data_con_func = 'first_hour_avg_day' - end = 0 - start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[4]) - start = to_int(start) - timeframe = translate_timeframe(timeframe) - log_text = 'serie_tagesmittelwert_tag_stunde_end|group' - required_params = [timeframe, data_con_func, start, end] - - elif db_addon_fct in ALL_GEN_ATTRIBUTES: - log_text = 'all_gen_attributes' - required_params = [] - - if required_params is None: + func = timeframe = timedelta = start = end = group = group2 = data_con_func = None + mandatory_params = None + + # handle all functions of cat 'wertehistorie' + if db_addon_fct_cat == 'wertehistorie': + + # handle functions of sub_cat 'onchange' like 'minmax_heute_max', 'minmax_heute_min', 'minmax_woche_max', 'minmax_woche_min' + if db_addon_fct_sub_cat == 'onchange': + timeframe = translate_timeframe(db_addon_fct_vars[1]) + func = db_addon_fct_vars[2] if db_addon_fct_vars[2] in ALLOWED_MINMAX_FUNCS else None + start = end = 0 + mandatory_params = [func, timeframe, start, end] + + # handle functions of sub_cat 'last' like 'minmax_last' in format 'minmax_last_timedelta|timeframe_function' like 'minmax_last_24h_max' + elif db_addon_fct_sub_cat == 'last': + func = db_addon_fct_vars[3] + start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[2]) + start = to_int(start) + timeframe = translate_timeframe(timeframe) + end = 0 + mandatory_params = [func, timeframe, start, end] + + # handle functions of sub_cat 'timeframe' like 'min/max/avg' in format 'minmax_timeframe_timedelta_func' like 'minmax_heute_minus2_max' + elif db_addon_fct_sub_cat == 'timeframe': + func = db_addon_fct_vars[3] # min, max, avg + timeframe = translate_timeframe(db_addon_fct_vars[1]) # day, week, month, year + start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) + mandatory_params = [func, timeframe, start, end] + + # handle all functions of cat 'zaehlerstand' + elif db_addon_fct_cat == 'zaehler': + + # handle functions of sub_cat 'timeframe' like 'zaehlerstand_timeframe_timedelta' like 'zaehlerstand_heute_minus1' + if db_addon_fct_sub_cat == 'timeframe': + func = 'last' + timeframe = translate_timeframe(db_addon_fct_vars[1]) + start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) + mandatory_params = [func, timeframe, start, end] + + # handle all functions of cat 'verbrauch' + elif db_addon_fct_cat == 'verbrauch': + # 'start' ist das Zeitinkrement von jetzt (0) für den Zählerstand zu Beginn der Betrachtung; 'end' ist das Zeitinkrement von jetzt (0) für den Zählerstand zum Ende der Betrachtung + + # handle functions of sub_cat 'onchange' in format 'verbrauch_timeframe' like 'verbrauch_heute', 'verbrauch_woche', 'verbrauch_monat', 'verbrauch_jahr' + if db_addon_fct_sub_cat == 'onchange': + timeframe = translate_timeframe(db_addon_fct_vars[1]) + end = 0 + start = end + 1 + mandatory_params = [timeframe, start, end] + + # handle functions of sub_cat 'last' in format 'verbrauch_last_timedelta|timeframe' like 'verbrauch_last_24h' + elif db_addon_fct_sub_cat == 'last': + start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[2]) + start = to_int(start) + timeframe = translate_timeframe(timeframe) + end = 0 + mandatory_params = [timeframe, start, end] + + # handle functions of sub_cat 'timeframe' in format 'verbrauch_timeframe_timedelta' like 'verbrauch_heute_minus2' + elif db_addon_fct_sub_cat == 'timeframe': + timeframe = translate_timeframe(db_addon_fct_vars[1]) + end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) + start = end + 1 + mandatory_params = [timeframe, start, end] + + # handle functions of sub_cat 'rolling' in format 'verbrauch_rolling_window_timeframe_timedelta' like 'verbrauch_rolling_12m_woche_minus1' + elif db_addon_fct_sub_cat == 'rolling': + func = db_addon_fct_vars[1] + window_inc, window_dur = split_sting_letters_numbers(db_addon_fct_vars[2]) + window_inc = to_int(window_inc) # 12 + window_dur = translate_timeframe(window_dur) # day, week, month, year + timeframe = translate_timeframe(db_addon_fct_vars[3]) # day, week, month, year + end = to_int(split_sting_letters_numbers(db_addon_fct_vars[4])[1]) + if window_dur in ALLOWED_QUERY_TIMEFRAMES and window_inc and timeframe and end: + start = to_int(timeframe_to_timeframe(timeframe, window_dur) * window_inc) + end + mandatory_params = [func, timeframe, start, end] + + # handle functions of sub_cat 'jahrzeit' in format 'verbrauch_jahreszeitraum_timedelta' like 'verbrauch_jahreszeitraum_minus1' + elif db_addon_fct_sub_cat == 'jahrzeit': + timeframe = translate_timeframe(db_addon_fct_vars[1]) # day, week, month, year + timedelta = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) + mandatory_params = [timeframe, timedelta] + + # handle all functions of cat 'tagesmittel' + elif db_addon_fct_cat == 'tagesmittel': + + # handle functions of sub_cat 'onchange' like 'tagesmitteltemperatur_timeframe' like 'tagesmitteltemperatur_heute', 'tagesmitteltemperatur_woche', 'tagesmitteltemperatur_monat', 'tagesmitteltemperatur_jahr' + if db_addon_fct_sub_cat == 'onchange': + timeframe = translate_timeframe(db_addon_fct_vars[1]) + start = end = 0 + mandatory_params = [timeframe, start, end] + + # handle functions of sub_cat 'timeframe' like 'tagesmitteltemperatur_timeframe_timedelta' like 'tagesmitteltemperatur_heute_minus1' + elif db_addon_fct_sub_cat == 'timeframe': + timeframe = translate_timeframe(db_addon_fct_vars[1]) + start = end = to_int(split_sting_letters_numbers(db_addon_fct_vars[2])[1]) + data_con_func = 'first_hour_avg_day' + mandatory_params = [timeframe, start, end, data_con_func] + + # handle all functions of cat 'serie' + elif db_addon_fct_cat == 'serie': + + # handle functions of sub_cat 'wertehistorie' in format 'serie_minmax_timeframe_func_start|group' like 'serie_minmax_monat_min_15m' + if db_addon_fct_sub_cat == 'wertehistorie': + func = db_addon_fct_vars[3] + timeframe = translate_timeframe(db_addon_fct_vars[2]) + start, group = split_sting_letters_numbers(db_addon_fct_vars[4]) + start = to_int(start) + group = translate_timeframe(group) + end = 0 + mandatory_params = [func, timeframe, start, end, group] + + # handle functions of sub_cat 'zaehler' in format 'serie_zaehlerstand_timeframe_start|group' like 'serie_zaehlerstand_tag_30d' + elif db_addon_fct_sub_cat == 'zaehler': + timeframe = translate_timeframe(db_addon_fct_vars[2]) + start, group = split_sting_letters_numbers(db_addon_fct_vars[3]) + start = to_int(start) + group = translate_timeframe(group) + mandatory_params = [timeframe, start, group] + + # handle functions of sub_cat 'verbrauch' in format 'serie_verbrauch_timeframe_start|group' like 'serie_verbrauch_tag_30d' + elif db_addon_fct_sub_cat == 'verbrauch': + timeframe = translate_timeframe(db_addon_fct_vars[2]) + start, group = split_sting_letters_numbers(db_addon_fct_vars[3]) + start = to_int(start) + group = translate_timeframe(group) + mandatory_params = [timeframe, start, group] + + # handle functions of sub_cat 'summe' in format 'serie_xxsumme_timeframe_count|group' like serie_waermesumme_monat_24m + elif db_addon_fct_sub_cat == 'summe': + func = 'sum_max' + start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[3]) + start = to_int(start) + timeframe = translate_timeframe(timeframe) + end = 0 + group = 'day', + group2 = 'month' + mandatory_params = [func, timeframe, start, end, group, group2] + + # handle functions of sub_cat 'mittel_d' in format 'serie_tagesmittelwert_count|group' like 'serie_tagesmittelwert_0d' => Tagesmittelwert der letzten 0 Tage (also heute) + elif db_addon_fct_sub_cat == 'mittel_d': + func = 'max' + timeframe = 'year' + start, group = split_sting_letters_numbers(db_addon_fct_vars[2]) + start = to_int(start) + group = translate_timeframe(group) + end = 0 + mandatory_params = [func, timeframe, start, end, group] + + # handle functions of sub_cat 'mittel_h' in format 'serie_tagesmittelwert_group2_count|group' like 'serie_tagesmittelwert_stunde_0d' => Stundenmittelwerte der letzten 0 Tage (also heute) + elif db_addon_fct_sub_cat == 'mittel_h': + func = 'avg1' + timeframe = 'day' + end = 0 + group = 'hour' + start, group2 = split_sting_letters_numbers(db_addon_fct_vars[3]) + start = to_int(start) + group2 = translate_timeframe(group2) + mandatory_params = [func, timeframe, start, end, group, group2] + + # handle functions of sub_cat 'mittel_h1' in format 'serie_tagesmittelwert_stunde_start_end|group' like 'serie_tagesmittelwert_stunde_30_0d' => Stundenmittelwerte von vor 30 Tagen bis vor 0 Tagen (also heute) + elif db_addon_fct_sub_cat == 'mittel_h1': + data_con_func = 'avg_hour' + start = to_int(db_addon_fct_vars[3]) + end, timeframe = split_sting_letters_numbers(db_addon_fct_vars[4]) + end = to_int(end) + timeframe = translate_timeframe(timeframe) + mandatory_params = [timeframe, data_con_func, start, end] + + # handle functions of sub_cat 'mittel_d_h' in format 'serie_tagesmittelwert_tag_stunde_end|group' like 'serie_tagesmittelwert_tag_stunde_30d' => Tagesmittelwert auf Basis des Mittelwerts pro Stunden für die letzten 30 Tage + elif db_addon_fct_sub_cat == 'mittel_d_h': + data_con_func = 'first_hour_avg_day' + end = 0 + start, timeframe = split_sting_letters_numbers(db_addon_fct_vars[4]) + start = to_int(start) + timeframe = translate_timeframe(timeframe) + mandatory_params = [timeframe, data_con_func, start, end] + + # handle functions of cat 'generic' + elif db_addon_fct_cat == 'gen': + mandatory_params = [] + + if mandatory_params is None: self.logger.warning(f"For calculating '{db_addon_fct}' at Item '{item.property.path}' no mandatory parameters given.") - return - - if required_params and None in required_params: - self.logger.warning(f"For calculating '{db_addon_fct}' at Item '{item.property.path}' not all mandatory parameters given. Definitions are: {func=}, {timeframe=}, {timedelta=}, {start=}, {end=}, {group=}, {group2=}, {data_con_func=}") - return + return None - # create dict and reduce dict to keys with value != None - param_dict = {'func': func, 'timeframe': timeframe, 'timedelta': timedelta, 'start': start, 'end': end, 'group': group, 'group2': group2, 'data_con_func': data_con_func} + if None in mandatory_params: + missing_params = [attr for attr, val in zip(['func', 'timeframe', 'timedelta', 'start', 'end', 'group', 'group2', 'data_con_func'], mandatory_params) if val is None] + self.logger.warning(f"Missing mandatory parameters for {db_addon_fct} at Item '{item.property.path}'. mandatory parameters={', '.join(missing_params)}") + return None - # return reduced dict w keys with value != None - return {k: v for k, v in param_dict.items() if v is not None} + return {k: v for k, v in locals().items() if k in ['func', 'timeframe', 'timedelta', 'start', 'end', 'group', 'group2', 'data_con_func'] and v is not None} def get_query_parameters_from_db_addon_params() -> Union[dict, None]: - """derives parameters from item attribute db_addon_params, if parameter for db_addon_fct are not sufficient - - possible_params may be given, if not, default value is used - required_params must be given + """Derives parameters from item attribute db_addon_params, if parameter for db_addon_fct are not sufficient. + Possible_params may be given if not, the default value is used. mandatory_params must be given. """ - db_addon_params = params_to_dict(self.get_iattr_value(item.conf, 'db_addon_params')) - - if not db_addon_params: - db_addon_params = self.get_iattr_value(item.conf, 'db_addon_params_dict') + # get required, optional and additional params for db_addon_func + mandatory_params, optional_params, additional_params = item_attribute_dict['params'] - if not db_addon_params: - db_addon_params = {} + # get db_addon_params from item + db_addon_params = params_to_dict(self.get_iattr_value(item.conf, 'db_addon_params')) or self.get_iattr_value(item.conf, 'db_addon_params_dict') or {} - new_db_addon_params = {} - possible_params = required_params = [] - - # create item config for all functions with 'summe' like waermesumme, kaeltesumme, gruenlandtemperatursumme - if db_addon_fct in ('kaeltesumme', 'waermesumme', 'gruenlandtempsumme'): - possible_params = ['year', 'month'] - - # create item config for wachstumsgradtage attributes - elif db_addon_fct == 'wachstumsgradtage': - possible_params = ['year', 'variant', 'threshold', 'result'] - - # create item config for kenntage attributes - elif db_addon_fct in ('wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage'): - possible_params = ['year', 'month'] - - # create item config for tagesmitteltemperatur - elif db_addon_fct == 'tagesmitteltemperatur': - possible_params = ['timeframe', 'count'] + # check if all required params are given + if not all(param in db_addon_params for param in mandatory_params): + self.logger.warning(f"Item '{item.property.path}' with {db_addon_fct=} ignored, since not all mandatory parameters {mandatory_params=} in {db_addon_params=} are given.") + return None - # create item config for minmax - elif db_addon_fct == 'minmax': - required_params = ['func', 'timeframe', 'start'] + # reduce db_addon_params from item to (optional_params + mandatory_params) + new_db_addon_params = {k: v for k, v in db_addon_params.items() if k in (optional_params + mandatory_params)} if db_addon_params else {} - # create item config for minmax_last - elif db_addon_fct == 'minmax_last': - required_params = ['func', 'timeframe', 'start', 'end'] + # check if parameter values are valid + if 'func' in new_db_addon_params: + if (db_addon_fct_cat == 'wertehistorie' and new_db_addon_params['func'] not in ALLOWED_MINMAX_FUNCS) or (db_addon_fct_cat == 'complex' and new_db_addon_params['func'] not in ALLOWED_QUERY_FUNCS): + self.logger.warning(f"Parameter 'func'={new_db_addon_params['timeframe']} of item '{item.property.path}' not valid. Item will be ignored.") + return None - # create item config for verbrauch - elif db_addon_fct == 'verbrauch': - required_params = ['timeframe', 'start', 'end'] + if 'timeframe' in new_db_addon_params and new_db_addon_params['timeframe'] not in ALLOWED_QUERY_TIMEFRAMES: + self.logger.warning(f"Parameter 'timeframe'={new_db_addon_params['timeframe']} of item '{item.property.path}' not valid. Valid parameter values: {ALLOWED_QUERY_TIMEFRAMES}. Item will be ignored.") + return None - # create item config for zaehlerstand - elif db_addon_fct == 'zaehlerstand': - required_params = ['timeframe', 'start'] + for param in ['start', 'end', 'threshold']: + if param in new_db_addon_params: + new_value = to_int(new_db_addon_params[param]) + if new_value is None: + self.logger.warning(f"Parameter '{param}'={new_db_addon_params[param]} of item '{item.property.path}' not valid. Parameter value need to be integer. Item will be ignored.") + return None + else: + new_db_addon_params[param] = new_value + + if 'year' in new_db_addon_params and not self._valid_year(new_db_addon_params['year']): + self.logger.warning(f"Parameter 'year'={new_db_addon_params['year']} of item '{item.property.path}' not valid. Item will be ignored.") + return None - # create item config for db_request and everything else (get_query_parameters_from_db_addon_fct) - else: - required_params = ['func', 'timeframe'] - possible_params = ['start', 'end', 'group', 'group2', 'ignore_value_list', 'use_oldest_entry'] + if 'month' in new_db_addon_params and not self._valid_month(new_db_addon_params['month']): + self.logger.warning(f"Parameter 'month'={new_db_addon_params['month']} of item '{item.property.path}' not valid. Item will be ignored.") + return None - if required_params and not any(param in db_addon_params for param in required_params): - self.logger.warning(f"Item '{item.property.path}' with {db_addon_fct=} ignored, since not all mandatory parameters in {db_addon_params=} are given. Item will be ignored.") - return + if 'result' in new_db_addon_params and new_db_addon_params['result'] not in ALLOWED_RESULT_TYPES: + self.logger.warning(f"Parameter 'result'={new_db_addon_params['result']} of item '{item.property.path}' not valid. Valid parameter values: {ALLOWED_RESULT_TYPES}. Item will be ignored.") + return None - # reduce dict to possible keys + required_params - for key in possible_params + required_params: - value = db_addon_params.get(key) - if value: - new_db_addon_params[key] = value + # add additional params + if additional_params: + new_db_addon_params.update(additional_params) return new_db_addon_params @@ -509,15 +509,6 @@ def get_database_item() -> Item: return None, None - def check_db_addon_fct(check_item) -> bool: - """ - Check if item has db_addon_fct and is onchange - """ - if self.has_iattr(check_item.conf, 'db_addon_fct'): - if self.get_iattr_value(check_item.conf, 'db_addon_fct').lower() in ONCHANGE_ATTRIBUTES: - return True - return False - def format_db_addon_ignore_value_list(optimize: bool = self.optimize_value_filter): """ Check of list of comparison operators is formally valid """ @@ -581,6 +572,51 @@ def format_db_addon_ignore_value_list(optimize: bool = self.optimize_value_filte return db_addon_ignore_value_list_optimized + # ToDo: check new coding + def format_db_addon_ignore_value_list_new(_db_addon_ignore_value_list: List[str], debug_log=False) -> Union[List[str], None]: + + max_values = {'!=': [], '>=': [], '<=': [], '>': [], '<': []} + db_addon_ignore_value_list_formatted = [] + + for _entry in _db_addon_ignore_value_list: + _entry = entry.strip() + for _op in max_values.keys(): + if _op in _entry: + _, _value = _entry.split(_op, 1) + _value = to_int_float(_value.strip()) + if _value is not None: + db_addon_ignore_value_list_formatted.append(f"{_op} {_value}") + max_values[_op].append(_value) + + if debug_log: + self.logger.debug(f"Summarized 'ignore_value_list': {db_addon_ignore_value_list_formatted}") + + if not db_addon_ignore_value_list_formatted: + return None + + # Optimizing the list + lower_values = max(max_values['<'] + max_values['<='], default=None) + upper_values = min(max_values['>'] + max_values['>='], default=None) + + db_addon_ignore_value_list_optimized = [ + f"< {lower_values}" if lower_values is not None else None, + f"> {upper_values}" if upper_values is not None else None + ] + [f"!= {v}" for v in max_values['!='] if (not lower_values or v >= lower_values) and (not upper_values or v <= upper_values)] + + db_addon_ignore_value_list_optimized = list(filter(None, db_addon_ignore_value_list_optimized)) + + if debug_log: + self.logger.debug(f"Optimized 'ignore_value_list': {db_addon_ignore_value_list_optimized}") + + return db_addon_ignore_value_list_optimized + + # check for pause item + if item.property.path == self._pause_item_path: + self.logger.debug(f'pause item {item.property.path} registered') + self._pause_item = item + self.add_item(item, updating=True) + return self.update_item + # handle all items with db_addon_fct if self.has_iattr(item.conf, 'db_addon_fct'): @@ -591,7 +627,9 @@ def format_db_addon_ignore_value_list(optimize: bool = self.optimize_value_filte db_addon_fct = self.get_iattr_value(item.conf, 'db_addon_fct').lower() # read item_attribute_dict aus item_attributes_master - item_attribute_dict = ITEM_ATTRIBUTES['db_addon_fct'].get(db_addon_fct) + item_attribute_dict = ITEM_ATTRIBUTES['db_addon_fct'].get(db_addon_fct, {}) + db_addon_fct_cat = item_attribute_dict['cat'] + db_addon_fct_sub_cat = item_attribute_dict['sub_cat'] # get query parameters from db_addon_fct or db_addon_params if item_attribute_dict['params']: @@ -638,7 +676,7 @@ def format_db_addon_ignore_value_list(optimize: bool = self.optimize_value_filte query_params.update({'ignore_value_list': db_addon_ignore_value_list_final}) # create standard items config - item_config_data_dict = {'db_addon': 'function', 'db_addon_fct': db_addon_fct, 'database_item': database_item, 'query_params': query_params, 'suspended': False} + item_config_data_dict = {'db_addon': 'function', 'db_addon_fct': db_addon_fct, 'database_item': database_item, 'query_params': query_params, 'suspended': False, 'cat': db_addon_fct_cat, 'sub_cat': db_addon_fct_sub_cat} if isinstance(database_item, str): item_config_data_dict.update({'database_item_path': True}) else: @@ -688,13 +726,13 @@ def format_db_addon_ignore_value_list(optimize: bool = self.optimize_value_filte elif self.has_iattr(item.conf, 'db_addon_info'): if self.debug_log.parse: self.logger.debug(f"parse item={item.property.path} due to used item attribute 'db_addon_info'") - self.add_item(item, config_data_dict={'db_addon': 'info', 'db_addon_fct': f"info_{self.get_iattr_value(item.conf, 'db_addon_info').lower()}", 'database_item': None, 'startup': True}) + self.add_item(item, config_data_dict={'db_addon': 'info', 'db_addon_fct': f"info_{self.get_iattr_value(item.conf, 'db_addon_info').lower()}", 'database_item': None, 'startup': True, 'cat': 'info', 'sub_cat': None}) # handle all items with db_addon_admin elif self.has_iattr(item.conf, 'db_addon_admin'): if self.debug_log.parse: self.logger.debug(f"parse item={item.property.path} due to used item attribute 'db_addon_admin'") - self.add_item(item, config_data_dict={'db_addon': 'admin', 'db_addon_fct': f"admin_{self.get_iattr_value(item.conf, 'db_addon_admin').lower()}", 'database_item': None}) + self.add_item(item, config_data_dict={'db_addon': 'admin', 'db_addon_fct': f"admin_{self.get_iattr_value(item.conf, 'db_addon_admin').lower()}", 'database_item': None, 'cat': 'admin', 'sub_cat': None}) return self.update_item # Reference to 'update_item' for all database items to trigger calculation of on-change items @@ -713,7 +751,17 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ - if self.alive and caller != self.get_shortname(): + # check for pause item + if item is self._pause_item: + if caller != self.get_fullname(): + self.logger.debug(f'pause item changed to {item()}') + if item() and self.alive: + self.stop() + elif not item() and not self.alive: + self.run() + return + + if self.alive and caller != self.get_fullname(): # handle database items if item in self._database_items(): self.logger.debug(f" Updated Item {item.property.path} with value {item()} will be put to queue in approx. {self.onchange_delay_time}s resp. after startup.") @@ -722,14 +770,12 @@ def update_item(self, item, caller=None, source=None, dest=None): # handle admin items elif self.has_iattr(item.conf, 'db_addon_admin'): self.logger.debug(f"update_item was called with item {item.property.path} from caller {caller}, source {source} and dest {dest}") - if self.get_iattr_value(item.conf, 'db_addon_admin') == 'suspend': - self.suspend(item()) - elif self.get_iattr_value(item.conf, 'db_addon_admin') == 'recalc_all': + if self.get_iattr_value(item.conf, 'db_addon_admin') == 'recalc_all': self.execute_all_items() - item(False, self.get_shortname()) + item(False, self.get_fullname()) elif self.get_iattr_value(item.conf, 'db_addon_admin') == 'clean_cache_values': self._init_cache_dicts() - item(False, self.get_shortname()) + item(False, self.get_fullname()) def _save_pickle(self, data) -> None: """Saves received data as pickle to given file""" @@ -912,7 +958,7 @@ def _create_due_items() -> list: _reset_items.update(set(self._onchange_yearly_items())) # reset der onchange items - [_item(0, self.get_shortname()) for _item in _reset_items] + [_item(0, self.get_fullname()) for _item in _reset_items] return list(_todo_items) @@ -998,9 +1044,13 @@ def handle_ondemand(self, item: Item) -> None: # get parameters item_config = self.get_item_config(item) + if self.debug_log.ondemand: self.logger.debug(f"Item={item.property.path} with {item_config=}") + db_addon_fct = item_config['db_addon_fct'] + db_addon_fct_cat = item_config['cat'] + db_addon_fct_sub_cat = item_config['sub_cat'] database_item = item_config['database_item'] query_params = item_config.get('query_params') if query_params: @@ -1009,45 +1059,53 @@ def handle_ondemand(self, item: Item) -> None: else: params = {} + # set default result + result = None + if self.debug_log.ondemand: self.logger.debug(f"{db_addon_fct=} will _query_item with {params=}.") - # handle item starting with 'verbrauch_' - if db_addon_fct in ALL_VERBRAUCH_ATTRIBUTES: + # handle all items of category 'verbrauch' + if db_addon_fct_cat == 'verbrauch': result = self._handle_verbrauch(params) if result and result < 0: self.logger.info(f"Result of item {item.property.path} with {db_addon_fct=} was negative. Something seems to be wrong.") - # handle 'serie_verbrauch' - elif db_addon_fct in SERIE_ATTRIBUTES_VERBRAUCH: - result = self._handle_verbrauch_serie(params) - - # handle item starting with 'zaehlerstand_' - elif db_addon_fct in ALL_ZAEHLERSTAND_ATTRIBUTES: + # handle all items of category 'zaehler' + elif db_addon_fct_cat == 'zaehler': result = self._handle_zaehlerstand(params) - # handle 'serie_zaehlerstand' - elif db_addon_fct in SERIE_ATTRIBUTES_ZAEHLERSTAND: - result = self._handle_zaehlerstand_serie(params) + # handle all items of category 'serie' + elif db_addon_fct_cat == 'serie': - # handle 'serie_tagesmittelwert_stunde_30_0d' and 'serie_tagesmittelwert_tag_stunde_30d' - elif db_addon_fct in SERIE_ATTRIBUTES_MITTEL_H1 + SERIE_ATTRIBUTES_MITTEL_D_H: - result = self._prepare_value_list(**params) + # handle all items of sub_category 'verbrauch' + if db_addon_fct_sub_cat == 'verbrauch': + result = self._handle_verbrauch_serie(params) - # handle TAGESMITTEL_ATTRIBUTES_TIMEFRAME like tagesmitteltemperatur_heute_minus1 - elif db_addon_fct in TAGESMITTEL_ATTRIBUTES_TIMEFRAME: + # handle all items of sub_category 'zaehler' + elif db_addon_fct_sub_cat == 'zaehler': + result = self._handle_zaehlerstand_serie(params) - params.update({'data_con_func': 'first_hour_avg_day'}) - _result = self._prepare_value_list(**params) + # handle items of sub_category 'mittel_h1' and 'mittel_h_d' like 'serie_tagesmittelwert_stunde_30_0d' and 'serie_tagesmittelwert_tag_stunde_30d' + elif db_addon_fct_sub_cat in ['mittel_h1', 'mittel_h_d']: + result = self._prepare_value_list(**params) - if isinstance(_result, list): - result = _result[0][1] - else: - result = None + # handle all items of category 'tagesmittel' + elif db_addon_fct_cat == 'tagesmittel': + + # handle all items of sub_category 'timeframe' like tagesmitteltemperatur_heute_minus1 + if db_addon_fct_sub_cat == 'timeframe': + _result = self._prepare_value_list(**params) - # handle all functions using temperature sums - elif db_addon_fct in ALL_SUMME_ATTRIBUTES: + if isinstance(_result, list): + result = _result[0][1] + + elif db_addon_fct_sub_cat == 'complex': + result = self._prepare_value_list(**params) + + # handle all items of category 'summe' + elif db_addon_fct_cat == 'summe': new_params = {} for entry in ('threshold', 'variant', 'result', 'data_con_func'): if entry in params: @@ -1066,7 +1124,7 @@ def handle_ondemand(self, item: Item) -> None: elif db_addon_fct == 'general_oldest_log': result = self._get_oldest_log(database_item) - # handle everything else + # handle everything else link db_request, minmax else: result = self._query_item(**params)[0][1] @@ -1082,7 +1140,7 @@ def handle_ondemand(self, item: Item) -> None: self.logger.info(f" Item value for '{item.property.path}' will be set to {result}") item_config = self.get_item_config(item) item_config.update({'value': result}) - item(result, self.get_shortname()) + item(result, self.get_fullname()) def handle_onchange(self, updated_item: Item, value: float) -> None: """ @@ -1191,38 +1249,36 @@ def handle_tagesmittel(): item_config = self.get_item_config(item) if self.debug_log.onchange: self.logger.debug(f"Item={item.property.path} with {item_config=}") - db_addon_fct = item_config['db_addon_fct'] + db_addon_fct_cat = item_config['cat'] + db_addon_fct_sub_cat = item_config['sub_cat'] database_item = item_config['database_item'] timeframe = item_config['query_params']['timeframe'] func = item_config['query_params'].get('func') ignore_value_list = item_config['query_params'].get('ignore_value_list') new_value = None - # handle all non on_change functions - if db_addon_fct not in ONCHANGE_ATTRIBUTES: + # handle all on_demand functions + if db_addon_fct_sub_cat != 'onchange': if self.debug_log.onchange: - self.logger.debug(f"non onchange function detected. Skip update.") + self.logger.debug(f"on demand function detected. Skip update.") continue - # handle minmax onchange items tagesmitteltemperatur_heute, minmax_heute_avg - if db_addon_fct in TAGESMITTEL_ATTRIBUTES_ONCHANGE: + # handle onchange tagesmittel items like tagesmitteltemperatur_heute + if db_addon_fct_cat == 'tagesmittel': new_value = handle_tagesmittel() - # handle minmax onchange items like minmax_heute_max, minmax_heute_min, minmax_woche_max, minmax_woche_min..... - elif db_addon_fct.startswith('minmax'): + # handle all onchange wertehistorie items like minmax_heute_max, minmax_heute_min, minmax_woche_max, minmax_woche_min..... + elif db_addon_fct_cat == 'wertehistorie': new_value = handle_minmax() - # handle verbrauch onchange items ending with heute, woche, monat, jahr - elif db_addon_fct.startswith('verbrauch'): + # handle onchange verbrauch items like verbrauch_heute + elif db_addon_fct_cat == 'verbrauch': new_value = handle_verbrauch() - if new_value is None: - continue - self.logger.info(f" Item value for '{item.property.path}' with func={func} will be set to {new_value}") item_config = self.get_item_config(item) item_config.update({'value': new_value}) - item(new_value, self.get_shortname()) + item(new_value, self.get_fullname()) def _update_database_items(self) -> None: """Turns given as database_item path into database_items""" @@ -1237,11 +1293,12 @@ def _update_database_items(self) -> None: else: item_config.update({'database_item': database_item}) db_addon_startup = bool(self.get_iattr_value(database_item.conf, 'db_addon_startup')) + del item_config['database_item_path'] if db_addon_startup: item_config.update({'startup': True}) def _suspend_item_calculation(self, item: Union[str, Item], suspended: bool = False) -> Union[bool, None]: - """suspend calculation od dedicated item""" + """suspend calculation of dedicated item""" if isinstance(item, str): item = self.items.return_item(item) @@ -1352,7 +1409,7 @@ def _all_items(self) -> list: # Public functions / Using item_path ######################################### - def gruenlandtemperatursumme(self, item_path: str, year: Union[int, str] = None, ignore_value_list: list = None) -> Union[int, None]: + def gruenlandtemperatursumme(self, item_path: str, year: Union[int, str] = None, ignore_value_list: list = None, result: str = 'total') -> Union[int, None]: """ Query database for gruenlandtemperatursumme for given year or year https://de.wikipedia.org/wiki/Gr%C3%BCnlandtemperatursumme @@ -1364,14 +1421,15 @@ def gruenlandtemperatursumme(self, item_path: str, year: Union[int, str] = None, :param item_path: item object or item_id for which the query should be done :param year: year the gruenlandtemperatursumme should be calculated for :param ignore_value_list: list of comparison operators for val_num, which will be applied during query + :param result: total-Gesamtwert, month-Serie mit Monatswerten, day-Serie mit Tageswerten (default: total) :return: gruenlandtemperatursumme """ item = self.items.return_item(item_path) if item: - return self._handle_temp_sums(func='gruendlandtempsumme', database_item=item, year=year, ignore_value_list=ignore_value_list) + return self._handle_temp_sums(func='gruendlandtempsumme', database_item=item, year=year, ignore_value_list=ignore_value_list, params={'result': result}) - def waermesumme(self, item_path: str, year: Union[int, str] = None, month: Union[int, str] = None, ignore_value_list: list = None, threshold: int = 0) -> Union[int, None]: + def waermesumme(self, item_path: str, year: Union[int, str] = None, month: Union[int, str] = None, ignore_value_list: list = None, threshold: int = 0, result: str = 'total') -> Union[int, None]: """ Query database for waermesumme for given year or year/month https://de.wikipedia.org/wiki/W%C3%A4rmesumme @@ -1381,14 +1439,15 @@ def waermesumme(self, item_path: str, year: Union[int, str] = None, month: Union :param month: month the waermesumme should be calculated for :param ignore_value_list: list of comparison operators for val_num, which will be applied during query :param threshold: threshold for temperature + :param result: total-Gesamtwert, month-Serie mit Monatswerten, day-Serie mit Tageswerten (default: total) :return: waermesumme """ item = self.items.return_item(item_path) if item: - return self._handle_temp_sums(func='waermesumme', database_item=item, year=year, month=month, ignore_value_list=ignore_value_list, params={'threshold': threshold}) + return self._handle_temp_sums(func='waermesumme', database_item=item, year=year, month=month, ignore_value_list=ignore_value_list, params={'threshold': threshold, 'result': result}) - def kaeltesumme(self, item_path: str, year: Union[int, str] = None, month: Union[int, str] = None, ignore_value_list: list = None) -> Union[int, None]: + def kaeltesumme(self, item_path: str, year: Union[int, str] = None, month: Union[int, str] = None, ignore_value_list: list = None, result: str = 'total') -> Union[int, None]: """ Query database for kaeltesumme for given year or year/month https://de.wikipedia.org/wiki/K%C3%A4ltesumme @@ -1397,14 +1456,15 @@ def kaeltesumme(self, item_path: str, year: Union[int, str] = None, month: Union :param year: year the kaeltesumme should be calculated for :param month: month the kaeltesumme should be calculated for :param ignore_value_list: list of comparison operators for val_num, which will be applied during query + :param result: total-Gesamtwert, month-Serie mit Monatswerten, day-Serie mit Tageswerten (default: total) :return: kaeltesumme """ item = self.items.return_item(item_path) if item: - return self._handle_temp_sums(func='kaeltesumme', database_item=item, year=year, month=month, ignore_value_list=ignore_value_list) + return self._handle_temp_sums(func='kaeltesumme', database_item=item, year=year, month=month, ignore_value_list=ignore_value_list, params={'result': result}) - def wachstumsgradtage(self, item_path: str, year: Union[int, str] = None, ignore_value_list: list = None, variant: int = 0, threshold: int = 10) -> Union[int, None]: + def wachstumsgradtage(self, item_path: str, year: Union[int, str] = None, ignore_value_list: list = None, variant: int = 0, threshold: int = 10, result: str = 'total') -> Union[int, None]: """ Query database for wachstumsgradtage https://de.wikipedia.org/wiki/Wachstumsgradtag @@ -1414,12 +1474,13 @@ def wachstumsgradtage(self, item_path: str, year: Union[int, str] = None, ignore :param ignore_value_list: list of comparison operators for val_num, which will be applied during query :param variant: variant to be used :param threshold: Temperature in °C as threshold: Ein Tage mit einer Tagesdurchschnittstemperatur oberhalb des Schwellenwertes gilt als Wachstumsgradtag + :param result: total-Gesamtwert, month-Serie mit Monatswerten, day-Serie mit Tageswerten (default: total) :return: wachstumsgradtage """ item = self.items.return_item(item_path) if item: - return self._handle_temp_sums(func='wachstumsgradtage', database_item=item, year=year, ignore_value_list=ignore_value_list, params={'threshold': threshold, 'variant': variant}) + return self._handle_temp_sums(func='wachstumsgradtage', database_item=item, year=year, ignore_value_list=ignore_value_list, params={'threshold': threshold, 'variant': variant, 'result': result}) def temperaturserie(self, item_path: str, year: Union[int, str] = None, ignore_value_list: list = None, data_con_func: str = 'first_hour_avg_day') -> Union[list, None]: """ @@ -1522,7 +1583,7 @@ def _handle_verbrauch(self, query_params: dict) -> Union[None, float]: - Ergibt diese Abfrage keinen Wert, Anfangszählerstand = 0 """ - # define start, end for verbrauch_jahreszeitraum_timedelta + # define start, end for verbrauch_jahreszeitraum_timedelta like 'verbrauch_jahreszeitraum_minus1' if 'timedelta' in query_params: timedelta = query_params.pop('timedelta') today = self.shtime.today(offset=0) @@ -1530,16 +1591,18 @@ def _handle_verbrauch(self, query_params: dict) -> Union[None, float]: end_date = today - relativedelta(years=timedelta) start = (today - start_date).days end = (today - end_date).days - else: - start = query_params['start'] - end = query_params['end'] + query_params.update({'start': start, 'end': end}) # calculate consumption if self.debug_log.prepare: self.logger.debug(f"called with {query_params=}") - # get value for end and check it; - query_params.update({'func': 'last', 'start': start, 'end': end}) + # extract start and end out of query_params + _start = query_params.pop('start') + _end = query_params.pop('end') + + # get value for end and check it + query_params.update({'func': 'last', 'start': _end, 'end': _end}) value_end = self._query_item(**query_params)[0][1] if self.debug_log.prepare: @@ -1548,8 +1611,9 @@ def _handle_verbrauch(self, query_params: dict) -> Union[None, float]: if value_end is None or value_end == 0: return value_end - # get value for start and check it; - query_params.update({'func': 'next', 'start': start, 'end': start}) + # get value for start and check it + # ToDo: Check if right start and end is used + query_params.update({'func': 'next', 'start': _start, 'end': _start}) value_start = self._query_item(**query_params)[0][1] if self.debug_log.prepare: self.logger.debug(f"{value_start=}") @@ -1583,16 +1647,18 @@ def _handle_verbrauch_serie(self, query_params: dict) -> list: for i in range(start, 1, -1): value = self._handle_verbrauch({'database_item': database_item, 'timeframe': timeframe, 'start': i + 1, 'end': i}) - ts_start, ts_end = self._get_start_end_as_timestamp(timeframe, i, i + 1) + # ToDo: check ts_start, ts_end + ts_start, ts_end = self._get_start_end_as_timestamp(timeframe=timeframe, start=(i + 1), end=i) + if self.debug_log.prepare: + self.logger.debug(f"{ts_start=}, {ts_end=}") series.append([ts_end, value]) return series + # ToDo: Test method def _handle_verbrauch_serie_new(self, query_params: dict) -> list: """Ermittlung einer Serie von Verbräuchen in einem Zeitraum für x Zeiträume""" - # ToDo: Test method - query_params.update({'data_con_func': 'max_day', 'cache': True}) raw_data = self._prepare_value_list(**query_params) @@ -1626,6 +1692,7 @@ def _handle_zaehlerstand(self, query_params: dict) -> Union[float, int, None]: # get last value of timeframe query_params.update({'func': 'next'}) last_value = self._query_item(**query_params)[0][1] + if self.debug_log.prepare: self.logger.debug(f"{last_value=}") @@ -1656,11 +1723,10 @@ def _handle_zaehlerstand_serie(self, query_params: dict) -> list: return series + # ToDo: Test method def _handle_zaehlerstand_serie_new(self, query_params: dict) -> list: """Ermittlung einer Serie von Zählerständen zum Ende eines Zeitraumes für x Zeiträume""" - # ToDo: Test method - query_params.update({'data_con_func': 'max_day', 'cache': True}) raw_data = self._prepare_value_list(**query_params) @@ -1692,11 +1758,13 @@ def _handle_temp_sums(self, func: str, database_item: Item, year: Union[int, str :return: temperature sum or day count - kaeltesumme: Kältesumme nach https://de.wikipedia.org/wiki/K%C3%A4ltesumme + params: result - waermesumme: Wärmesumme https://de.wikipedia.org/wiki/W%C3%A4rmesumme - params: threshold + params: threshold, result - gruenlandtempsumme: Grünlandtemperatursumme: https://de.wikipedia.org/wiki/Gr%C3%BCnlandtemperatursumme + params: result - wachstumsgradtage: Wachstumsgradtage https://de.wikipedia.org/wiki/Wachstumsgradtag - params: threshold, variant, result + params: year, threshold, variant, result - temperaturserie: Temperaturserie provide list of lists having timestamp and temperature(s) per day params: data_con_func - wuestentage: Wüstentage, Anzahl der Tage mit Tmax ≥ 35 °C @@ -1731,103 +1799,208 @@ def _handle_temp_sums(self, func: str, database_item: Item, year: Union[int, str if not params: params = dict() - def kaeltesumme() -> float: + def kaeltesumme() -> Union[list, float, None]: """Berechnung der Kältesumme durch Akkumulieren aller negativen Tagesdurchschnittstemperaturen im Abfragezeitraum - :return: value of kaeltesumme + result 'total': Rückgabe als Gesamtwert + result 'month': Rückgabe als Liste mit kumulierten Werten pro Monat [['timestamp1', 'kumulierter Wert am Ende von Monat1'], ['timestamp2', ''kumulierter Wert am Ende von Monat2', [...], ...] + result 'day': Rückgabe als Liste mit kumulierten Werten pro Tag [['timestamp1', 'kumulierter Wert am Ende von Tag1'], ['timestamp2', ''kumulierter Wert am Ende von Tag2', [...], ...] """ + # define defaults + ks_total = 0 + ks_serie_day = [] + ks_serie_month = {} + + # get result type + result = params.get('result', 'total') + # akkumulieren alle Werte, kleiner 0 - ks = 0 for entry in raw_data: - if entry[1] < 0: - ks -= entry[1] - return int(round(ks, 0)) + timestamp, value = entry + + # limit values to negtive values + ks_day = min(0, value) - def waermesumme() -> float: + # create total value of kaeltesumme + ks_total -= ks_day + + # create series kaeltesumme per day + ks_serie_day.append([timestamp, round(ks_day, 1)]) + + # create series kaeltesumme per month + _dt = datetime.datetime.fromtimestamp(timestamp) + _dt = _dt.replace(day=1, minute=0, hour=0) + _timestamp = self._datetime_to_timestamp(_dt) + ks_serie_month[_timestamp] = ks_serie_month.get(_timestamp, 0) + ks_day + + # return result + if result == 'day': + return ks_serie_day + elif result == 'month': + return [[k, round(v, 1)] for k, v in ks_serie_month.items()] + return int(round(ks_total, 0)) + + def waermesumme() -> Union[list, float, None]: """Berechnung der Wärmesumme durch Akkumulieren aller Tagesdurchschnittstemperaturen im Abfragezeitraum, die größer/gleich dem Schwellenwert sind - :return: value of waermesumme + threshold: Schwellwert + result 'total': Rückgabe als Gesamtwert + result 'month': Rückgabe als Liste mit kumulierten Werten pro Monat [['timestamp1', 'kumulierter Wert am Ende von Monat1'], ['timestamp2', ''kumulierter Wert am Ende von Monat2', [...], ...] + result 'day': Rückgabe als Liste mit kumulierten Werten pro Tag [['timestamp1', 'kumulierter Wert am Ende von Tag1'], ['timestamp2', ''kumulierter Wert am Ende von Tag2', [...], ...] """ # get threshold and set to min 0 - threshold = params.get('threshold', 10) - threshold = max(0, threshold) + threshold = max(params.get('threshold', 10), 0) + + # get result type + result = params.get('result', 'total') + + # define defaults + ws_total = 0 + ws_serie_day = [] + ws_serie_month = {} # akkumulieren alle Werte, größer/gleich Schwellenwert - ws = 0 for entry in raw_data: - if entry[1] >= threshold: - ws += entry[1] - return int(round(ws, 0)) + timestamp, value = entry + + # limit values per threshold + ws_day = value if value >= threshold else 0 + + # create total value of waermesumme + ws_total += ws_day + + # create series kaeltesumme per day + ws_serie_day.append([timestamp, round(ws_day, 1)]) + + # create series kaeltesumme per month + _dt = datetime.datetime.fromtimestamp(timestamp) + _dt = _dt.replace(day=1, minute=0, hour=0) + _timestamp = self._datetime_to_timestamp(_dt) + ws_serie_month[_timestamp] = ws_serie_month.get(_timestamp, 0) + ws_day + + # return result + if result == 'day': + return ws_serie_day + elif result == 'month': + return [[k, round(v, 1)] for k, v in ws_serie_month.items()] + return int(round(ws_total, 0)) - def gruenlandtempsumme() -> float: + def gruenlandtempsumme() -> Union[list, float, None]: """Berechnung der Grünlandtemperatursumme durch Akkumulieren alle positiven Tagesmitteltemperaturen, im Januar gewichtet mit 50%, im Februar mit 75% - :return: value of gruenlandtempsumme + result 'total': Rückgabe als Gesamtwert + result 'month': Rückgabe als Liste mit kumulierten Werten pro Monat [['timestamp1', 'kumulierter Wert am Ende von Monat1'], ['timestamp2', ''kumulierter Wert am Ende von Monat2', [...], ...] + result 'day': Rückgabe als Liste mit kumulierten Werten pro Tag [['timestamp1', 'kumulierter Wert am Ende von Tag1'], ['timestamp2', ''kumulierter Wert am Ende von Tag2', [...], ...] """ - - gts = 0 + # define defaults + gts_total = 0 + gts_serie_day = [] + gts_serie_month = {} + + # get result type + result = params.get('result', 'total') + + # accumulate value for entry in raw_data: timestamp, value = entry - if value > 0: - dt = self._timestamp_to_datetime(timestamp / 1000) - if dt.month == 1: - value = value * 0.5 - elif dt.month == 2: - value = value * 0.75 - gts += value - return int(round(gts, 0)) + + # limit values to positive values + gts_day = max(0, value) + + # degrade values for january and february + dt = self._timestamp_to_datetime(timestamp / 1000) + if dt.month == 1: + gts_day = gts_day * 0.5 + elif dt.month == 2: + gts_day = gts_day * 0.75 + + # create total value of gruenlandtempsumme + gts_total += gts_day + + # create series gruenlandtempsumme per day + gts_serie_day.append([timestamp, round(gts_day, 1)]) + + # create series gruenlandtempsumme per month + _dt = datetime.datetime.fromtimestamp(timestamp) + _dt = _dt.replace(day=1, minute=0, hour=0) + _timestamp = self._datetime_to_timestamp(_dt) + gts_serie_month[_timestamp] = gts_serie_month.get(_timestamp, 0) + gts_day + + # return result + if result == 'day': + return gts_serie_day + elif result == 'month': + return [[k, round(v, 1)] for k, v in gts_serie_month.items()] + return int(round(gts_total, 0)) def wachstumsgradtage() -> Union[list, float, None]: """Berechnet die Wachstumsgradtage noch 2 möglichen Varianten und gibt entweder den Gesamtwert oder eine Liste mit kumulierten Werten pro Tag zurück + threshold: Schwellwert variant 0: Berechnungsmethode "Berechnung des einfachen Durchschnitts" mit Vergleich des Durchschnitts der täglichen Minimal- und Maximaltemperatur mit Schwellenwert. Maximaltemperaturen werden bei 30 °C gekappt. variant 1: Berechnungsmethode "modifizierte Berechnung des einfachen Durchschnitts" mit Vergleich des Durchschnitts der täglichen Minimal- und Maximaltemperatur mit Schwellenwert. Vor der Berechnung des Durchschnittes wird jede Temperatur, die den Schwellenwert unterschreitet, auf den Schwellenwert geändert. Maximaltemperaturen werden bei 30 °C gekappt. - - result 'value': Rückgabe als Gesamtwert - result 'series: Rückgabe als Liste mit kumulierten Werten pro Tag zurück [['timestamp1', 'kumulierter Wert am Ende von Tag1'], ['timestamp2', ''kumulierter Wert am Ende von Tag2', [...], ...] + result 'total': Rückgabe als Gesamtwert + result 'month': Rückgabe als Liste mit kumulierten Werten pro Monat [['timestamp1', 'kumulierter Wert am Ende von Monat1'], ['timestamp2', ''kumulierter Wert am Ende von Monat2', [...], ...] + result 'day': Rückgabe als Liste mit kumulierten Werten pro Tag [['timestamp1', 'kumulierter Wert am Ende von Tag1'], ['timestamp2', ''kumulierter Wert am Ende von Tag2', [...], ...] """ # define defaults - wgte = 0 - wgte_list = [] + wgt_total = 0 + wgt_serie_day = [] + wgt_serie_month = {} upper_limit = 30 - + # get threshold and set to min 0 - threshold = params.get('threshold', 10) - threshold = max(0, threshold) + threshold = max(params.get('threshold', 10), 0) # get variant variant = params.get('variant', 0) # get result type - result = params.get('result', 'value') + result = params.get('result', 'total') # variant handling if variant == 0: - self.logger.info(f"Calculate 'Wachstumsgradtage' according to 'Berechnung des einfachen Durchschnitts'.") + self.logger.info(f"Calculate 'Wachstumsgradtage' according to 'Berechnung des einfachen Durchschnitts' to {result=}.") min_val_c = 'min_val' elif variant == 1: - self.logger.info(f"Calculate 'Wachstumsgradtage' according to 'Modifizierte Berechnung des einfachen Durchschnitts'.") + self.logger.info(f"Calculate 'Wachstumsgradtage' according to 'Modifizierte Berechnung des einfachen Durchschnitts' to {result=}.") min_val_c = 'max(threshold, min_val)' else: self.logger.warning(f"Requested variant of 'Wachstumsgradtage' not defined. Aborting...") return - # accumulate values + # accumulate value for entry in raw_data: timestamp, min_val, max_val = entry - wgt = ((eval(min_val_c) + min(upper_limit, max_val)) / 2 ) - threshold - if wgt > 0: - wgte += wgt - wgte_list.append([timestamp, int(round(wgte, 0))]) + + # calc wachstumsgradtage per day + wgt_day = ((eval(min_val_c) + min(upper_limit, max_val)) / 2) - threshold + wgt_day = max(0, wgt_day) + + # create total value of wachstumsgradtage + wgt_total += wgt_day + + # create series wachstumsgradtage per day + wgt_serie_day.append([timestamp, round(wgt_day, 1)]) + + # create series wachstumsgradtage per month + _dt = datetime.datetime.fromtimestamp(timestamp) + _dt = _dt.replace(day=1, minute=0, hour=0) + _timestamp = self._datetime_to_timestamp(_dt) + wgt_serie_month[_timestamp] = wgt_serie_month.get(_timestamp, 0) + wgt_day # return result - return wgte_list if result == 'series' else int(round(wgte, 0)) + if result == 'day': + return wgt_serie_day + elif result == 'month': + return [[k, round(v, 1)] for k, v in wgt_serie_month.items()] + return int(round(wgt_total, 0)) def temperaturserie() -> list: """provide list of lists having timestamp and temperature(s) per day""" @@ -1867,12 +2040,8 @@ def vegetationstage() -> int: return _count(operator.ge, 'avg', 5) def _count(op, minmax: str, limit: int) -> int: - count = 0 - for entry in raw_data: - value = entry[2] if minmax == 'max' else entry[1] - if op(value, limit): - count += 1 - return count + minmax_index = 2 if minmax == 'max' else 1 + return sum(1 for entry in raw_data if op(entry[minmax_index], limit)) self.logger.debug(f"{func=}, {database_item=}, {year=}, {month=}, {params=}") @@ -1895,9 +2064,9 @@ def _count(op, minmax: str, limit: int) -> int: # define start_date, end_date if month is None: - ((s_y, s_m, s_d), (e_y, e_m, e_d)) = defaults.get(func, {}).get('start_end', timeframe[3]) - start_date = datetime.date(int(year) + s_y, s_m, s_d) - end_date = datetime.date(int(year) + e_y, e_m, e_d) + ((start_year, start_month, start_day), (end_year, end_month, end_day)) = defaults.get(func, {}).get('start_end', timeframe[3]) + start_date = datetime.date(int(year) + start_year, start_month, start_day) + end_date = datetime.date(int(year) + end_year, end_month, end_day) elif self._valid_month(month): start_date = datetime.date(int(year), int(month), 1) end_date = start_date + relativedelta(months=+1) - datetime.timedelta(days=1) @@ -1960,24 +2129,25 @@ def _prepare_value_list(self, database_item: Item, timeframe: str, start: int, e def _group_value_by_datetime_block(block: str) -> dict: """ - create dict of datetimes (per day or hour) and values based on database query result in format {'datetime1': [values]}, 'datetime1': [values], ..., 'datetimex': [values]} + create dict of datetimes (per day or hour) and values based on database query result in format {{'datetime1': [values]}, 'datetime1': [values], ..., 'datetimex': [values]} :param block: defined the increment of datetime, default is min, further possible is 'day' and 'hour' """ _value_dict = {} - for _entry in raw_data: - ts = _entry[0] + + for ts, value in raw_data: + # format timestamp if len(str(ts)) > 10: ts = ts / 1000 - dt = self._timestamp_to_datetime(ts) - dt = dt.replace(second=0, microsecond=0, tzinfo=None) + # format datetime object + dt = self._timestamp_to_datetime(ts).replace(second=0, microsecond=0, tzinfo=None) if block == 'hour': dt = dt.replace(minute=0) if block == 'day': dt = dt.replace(minute=0, hour=0) - if dt not in _value_dict: - _value_dict[dt] = [] - _value_dict[dt].append(_entry[1]) + # fill dict + _value_dict.setdefault(dt, []).append(value) + return dict(sorted(_value_dict.items())) def _concentrate_values(option: str) -> list: @@ -2091,10 +2261,10 @@ def _check_db_existence(self) -> bool: if not _db_plugin: self.logger.error(f"Database plugin not loaded or given ConfigName {self.db_configname} not correct. No need for DatabaseAddOn Plugin.") return False - else: - self.logger.debug(f"Corresponding plugin 'database' with given config name '{self.db_configname}' found.") - self._db_plugin = _db_plugin - return self._get_db_parameter() + + self.logger.debug(f"Corresponding plugin 'database' with given config name '{self.db_configname}' found.") + self._db_plugin = _db_plugin + return self._get_db_parameter() def _get_db_parameter(self) -> bool: """ @@ -2122,11 +2292,10 @@ def _get_db_parameter(self) -> bool: self.item_attribute_search_str = f"{self.item_attribute_search_str}@{self.db_instance}" self.connection_data = self._db_plugin.get_parameter_value('connect') # pymsql ['host:localhost', 'user:smarthome', 'passwd:smarthome', 'db:smarthome', 'port:3306'] self.logger.debug(f"Database Plugin available with instance={self.db_instance} and connection={self.connection_data}") + return True except Exception as e: self.logger.error(f"Error {e} occurred during getting database plugin parameters. DatabaseAddOn Plugin not loaded.") return False - else: - return True def _check_db_connection_setting(self) -> None: """ @@ -2175,7 +2344,7 @@ def _get_oldest_value(self, item: Item) -> Union[int, float, bool]: Get value of the oldest log of item from cache dict or get value from db and put it to cache dict :param item: Item, for which query should be done - :return: oldest value + :return: the oldest value """ _oldest_entry = self.item_cache.get(item, {}).get('oldest_entry', None) @@ -2471,8 +2640,7 @@ def _valid_year(self, year: Union[int, str]) -> bool: if ((isinstance(year, int) or (isinstance(year, str) and year.isdigit())) and ( 1980 <= int(year) <= self.shtime.today(offset=0).year)) or (isinstance(year, str) and year == 'current'): return True - else: - return False + return False @staticmethod def _valid_month(month: Union[int, str]) -> bool: @@ -2480,8 +2648,7 @@ def _valid_month(month: Union[int, str]) -> bool: if (isinstance(month, int) or (isinstance(month, str) and month.isdigit())) and (1 <= int(month) <= 12): return True - else: - return False + return False ################################# # Database Query Preparation @@ -2555,7 +2722,7 @@ def _query_log_timestamp(self, func: str, item_id: int, ts_start: int, ts_end: i 'last': 'LIMIT 1 ', } - _where = "item_id = :item_id AND time <= :ts_start " if func == "next" else "item_id = :item_id AND time BETWEEN :ts_start AND :ts_end " + _where = "item_id = :item_id AND time <= :ts_end " if func == "next" else "item_id = :item_id AND time BETWEEN :ts_start AND :ts_end " _db_table = 'log ' @@ -2607,7 +2774,7 @@ def _query_log_timestamp(self, func: str, item_id: int, ts_start: int, ts_end: i # set params params = {'item_id': item_id, 'ts_start': ts_start, 'ts_end': ts_end} if func == "next": - params.pop('ts_end', None) + params.pop('ts_start', None) # assemble query query = f"SELECT {_select[func]}FROM {_db_table}WHERE {_where}{_group_by.get(group, '')}{_order.get(func, '')}{_limit.get(func, '')}{_table_alias.get(func, '')}{_group_by.get(group2, '')}".strip() @@ -2872,30 +3039,28 @@ def __post_init__(self, log_level): # Helper functions ####################### - -def params_to_dict(string: str) -> Union[dict, None]: +def params_to_dict(string: str) -> Union[Dict[str, Union[str, int]], None]: """Parse a string with named arguments and comma separation to dict; (e.g. string = 'year=2022, month=12')""" + res_dict = {} try: - res_dict = dict((a.strip(), b.strip()) for a, b in (element.split('=') for element in string.split(', '))) - except Exception: + for element in string.split(','): + key, value = element.split('=') + key, value = key.strip(), value.strip().strip('\'"') + if value.isdigit(): + value = int(value) + res_dict[key] = value + except AttributeError: + return None + except ValueError: return None - else: - # convert to int and remove possible double quotes - for key in res_dict: - if isinstance(res_dict[key], str): - res_dict[key] = res_dict[key].replace('"', '') - res_dict[key] = res_dict[key].replace("'", "") - if res_dict[key].isdigit(): - res_dict[key] = int(float(res_dict[key])) - - # check correctness if known key values (func=str, item, timeframe=str, start=int, end=int, count=int, group=str, group2=str, year=int, month=int): - for key in res_dict: - if key in ('func', 'timeframe', 'group', 'group2') and not isinstance(res_dict[key], str): - return None - elif key in ('start', 'end', 'count') and not isinstance(res_dict[key], int): - return None - return res_dict + + known_keys = {'func': str, 'item': str, 'timeframe': str, 'start': int, 'end': int, 'count': int, 'group': str, 'group2': str, 'year': int, 'month': int} + for key, value in res_dict.items(): + if key in known_keys and not isinstance(value, known_keys[key]): + return None + + return res_dict def translate_timeframe(timeframe: str) -> str: @@ -2930,7 +3095,7 @@ def timeframe_to_timeframe(timeframe_in: str, timeframe_out: str) -> int: _w_in_m = _w_in_y / _m_in_y _d_in_m = _d_in_y / _m_in_y - lookup = { + conversion_factors = { 'hour': {'hour': 1, 'day': _h_in_d, 'week': _h_in_d * _d_in_w, @@ -2963,7 +3128,7 @@ def timeframe_to_timeframe(timeframe_in: str, timeframe_out: str) -> int: } } - return lookup[timeframe_in][timeframe_out] + return conversion_factors[timeframe_in][timeframe_out] def to_int(arg) -> Union[int, None]: @@ -3003,3 +3168,5 @@ def split_sting_letters_numbers(string) -> list: ALLOWED_QUERY_TIMEFRAMES = ['year', 'month', 'week', 'day', 'hour'] ALLOWED_MINMAX_FUNCS = ['min', 'max', 'avg'] +ALLOWED_QUERY_FUNCS = ['avg', 'avg1', 'min', 'max', 'max1', 'sum', 'on', 'integrate', 'sum_max', 'sum_avg', 'sum_min_neg', 'diff_max', 'next', 'raw', 'first', 'last'] +ALLOWED_RESULT_TYPES = ['total', 'month', 'day'] diff --git a/db_addon/item_attributes.py b/db_addon/item_attributes.py deleted file mode 100644 index 696ffda30..000000000 --- a/db_addon/item_attributes.py +++ /dev/null @@ -1,75 +0,0 @@ -# !/usr/bin/env python -# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Copyright 2023 Michael Wenzel -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# DatabaseAddOn for SmartHomeNG. https://github.com/smarthomeNG// -# -# This plugin is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This plugin is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this plugin. If not, see . -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - - -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# -# -# THIS FILE IS AUTOMATICALLY CREATED BY USING item_attributes_master.py -# -# -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - -ONCHANGE_ATTRIBUTES = ['verbrauch_heute', 'verbrauch_tag', 'verbrauch_woche', 'verbrauch_monat', 'verbrauch_jahr', 'minmax_heute_min', 'minmax_heute_max', 'minmax_heute_avg', 'minmax_tag_min', 'minmax_tag_max', 'minmax_tag_avg', 'minmax_woche_min', 'minmax_woche_max', 'minmax_monat_min', 'minmax_monat_max', 'minmax_jahr_min', 'minmax_jahr_max', 'tagesmitteltemperatur_heute', 'tagesmitteltemperatur_tag'] -ONCHANGE_HOURLY_ATTRIBUTES = [] -ONCHANGE_DAILY_ATTRIBUTES = ['verbrauch_heute', 'verbrauch_tag', 'minmax_heute_min', 'minmax_heute_max', 'minmax_heute_avg', 'minmax_tag_min', 'minmax_tag_max', 'minmax_tag_avg', 'tagesmitteltemperatur_heute', 'tagesmitteltemperatur_tag'] -ONCHANGE_WEEKLY_ATTRIBUTES = ['verbrauch_woche', 'minmax_woche_min', 'minmax_woche_max'] -ONCHANGE_MONTHLY_ATTRIBUTES = ['verbrauch_monat', 'minmax_monat_min', 'minmax_monat_max'] -ONCHANGE_YEARLY_ATTRIBUTES = ['verbrauch_jahr', 'minmax_jahr_min', 'minmax_jahr_max'] -ONDEMAND_ATTRIBUTES = ['verbrauch_last_24h', 'verbrauch_last_7d', 'verbrauch_heute_minus1', 'verbrauch_heute_minus2', 'verbrauch_heute_minus3', 'verbrauch_heute_minus4', 'verbrauch_heute_minus5', 'verbrauch_heute_minus6', 'verbrauch_heute_minus7', 'verbrauch_heute_minus8', 'verbrauch_tag_minus1', 'verbrauch_tag_minus2', 'verbrauch_tag_minus3', 'verbrauch_tag_minus4', 'verbrauch_tag_minus5', 'verbrauch_tag_minus6', 'verbrauch_tag_minus7', 'verbrauch_tag_minus8', 'verbrauch_woche_minus1', 'verbrauch_woche_minus2', 'verbrauch_woche_minus3', 'verbrauch_woche_minus4', 'verbrauch_monat_minus1', 'verbrauch_monat_minus2', 'verbrauch_monat_minus3', 'verbrauch_monat_minus4', 'verbrauch_monat_minus12', 'verbrauch_jahr_minus1', 'verbrauch_jahr_minus2', 'verbrauch_jahr_minus3', 'verbrauch_rolling_12m_heute_minus1', 'verbrauch_rolling_12m_tag_minus1', 'verbrauch_rolling_12m_woche_minus1', 'verbrauch_rolling_12m_monat_minus1', 'verbrauch_rolling_12m_jahr_minus1', 'verbrauch_jahreszeitraum_minus1', 'verbrauch_jahreszeitraum_minus2', 'verbrauch_jahreszeitraum_minus3', 'zaehlerstand_heute_minus1', 'zaehlerstand_heute_minus2', 'zaehlerstand_heute_minus3', 'zaehlerstand_tag_minus1', 'zaehlerstand_tag_minus2', 'zaehlerstand_tag_minus3', 'zaehlerstand_woche_minus1', 'zaehlerstand_woche_minus2', 'zaehlerstand_woche_minus3', 'zaehlerstand_monat_minus1', 'zaehlerstand_monat_minus2', 'zaehlerstand_monat_minus3', 'zaehlerstand_jahr_minus1', 'zaehlerstand_jahr_minus2', 'zaehlerstand_jahr_minus3', 'minmax_last_24h_min', 'minmax_last_24h_max', 'minmax_last_24h_avg', 'minmax_last_7d_min', 'minmax_last_7d_max', 'minmax_last_7d_avg', 'minmax_heute_minus1_min', 'minmax_heute_minus1_max', 'minmax_heute_minus1_avg', 'minmax_heute_minus2_min', 'minmax_heute_minus2_max', 'minmax_heute_minus2_avg', 'minmax_heute_minus3_min', 'minmax_heute_minus3_max', 'minmax_heute_minus3_avg', 'minmax_tag_minus1_min', 'minmax_tag_minus1_max', 'minmax_tag_minus1_avg', 'minmax_tag_minus2_min', 'minmax_tag_minus2_max', 'minmax_tag_minus2_avg', 'minmax_tag_minus3_min', 'minmax_tag_minus3_max', 'minmax_tag_minus3_avg', 'minmax_woche_minus1_min', 'minmax_woche_minus1_max', 'minmax_woche_minus1_avg', 'minmax_woche_minus2_min', 'minmax_woche_minus2_max', 'minmax_woche_minus2_avg', 'minmax_monat_minus1_min', 'minmax_monat_minus1_max', 'minmax_monat_minus1_avg', 'minmax_monat_minus2_min', 'minmax_monat_minus2_max', 'minmax_monat_minus2_avg', 'minmax_jahr_minus1_min', 'minmax_jahr_minus1_max', 'minmax_jahr_minus1_avg', 'tagesmitteltemperatur_heute_minus1', 'tagesmitteltemperatur_heute_minus2', 'tagesmitteltemperatur_heute_minus3', 'tagesmitteltemperatur_tag_minus1', 'tagesmitteltemperatur_tag_minus2', 'tagesmitteltemperatur_tag_minus3', 'serie_minmax_monat_min_15m', 'serie_minmax_monat_max_15m', 'serie_minmax_monat_avg_15m', 'serie_minmax_woche_min_30w', 'serie_minmax_woche_max_30w', 'serie_minmax_woche_avg_30w', 'serie_minmax_tag_min_30d', 'serie_minmax_tag_max_30d', 'serie_minmax_tag_avg_30d', 'serie_verbrauch_tag_30d', 'serie_verbrauch_woche_30w', 'serie_verbrauch_monat_18m', 'serie_zaehlerstand_tag_30d', 'serie_zaehlerstand_woche_30w', 'serie_zaehlerstand_monat_18m', 'serie_waermesumme_monat_24m', 'serie_kaeltesumme_monat_24m', 'serie_tagesmittelwert_0d', 'serie_tagesmittelwert_stunde_0d', 'serie_tagesmittelwert_stunde_30_0d', 'serie_tagesmittelwert_tag_stunde_30d', 'general_oldest_value', 'general_oldest_log', 'kaeltesumme', 'waermesumme', 'gruenlandtempsumme', 'wachstumsgradtage', 'wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage', 'tagesmitteltemperatur', 'db_request', 'minmax', 'minmax_last', 'verbrauch', 'zaehlerstand'] -ONDEMAND_HOURLY_ATTRIBUTES = ['verbrauch_last_24h', 'verbrauch_last_7d'] -ONDEMAND_DAILY_ATTRIBUTES = ['verbrauch_heute_minus1', 'verbrauch_heute_minus2', 'verbrauch_heute_minus3', 'verbrauch_heute_minus4', 'verbrauch_heute_minus5', 'verbrauch_heute_minus6', 'verbrauch_heute_minus7', 'verbrauch_heute_minus8', 'verbrauch_tag_minus1', 'verbrauch_tag_minus2', 'verbrauch_tag_minus3', 'verbrauch_tag_minus4', 'verbrauch_tag_minus5', 'verbrauch_tag_minus6', 'verbrauch_tag_minus7', 'verbrauch_tag_minus8', 'verbrauch_rolling_12m_heute_minus1', 'verbrauch_rolling_12m_tag_minus1', 'verbrauch_jahreszeitraum_minus1', 'verbrauch_jahreszeitraum_minus2', 'verbrauch_jahreszeitraum_minus3', 'zaehlerstand_heute_minus1', 'zaehlerstand_heute_minus2', 'zaehlerstand_heute_minus3', 'zaehlerstand_tag_minus1', 'zaehlerstand_tag_minus2', 'zaehlerstand_tag_minus3', 'minmax_last_24h_min', 'minmax_last_24h_max', 'minmax_last_24h_avg', 'minmax_last_7d_min', 'minmax_last_7d_max', 'minmax_last_7d_avg', 'minmax_heute_minus1_min', 'minmax_heute_minus1_max', 'minmax_heute_minus1_avg', 'minmax_heute_minus2_min', 'minmax_heute_minus2_max', 'minmax_heute_minus2_avg', 'minmax_heute_minus3_min', 'minmax_heute_minus3_max', 'minmax_heute_minus3_avg', 'minmax_tag_minus1_min', 'minmax_tag_minus1_max', 'minmax_tag_minus1_avg', 'minmax_tag_minus2_min', 'minmax_tag_minus2_max', 'minmax_tag_minus2_avg', 'minmax_tag_minus3_min', 'minmax_tag_minus3_max', 'minmax_tag_minus3_avg', 'tagesmitteltemperatur_heute_minus1', 'tagesmitteltemperatur_heute_minus2', 'tagesmitteltemperatur_heute_minus3', 'tagesmitteltemperatur_tag_minus1', 'tagesmitteltemperatur_tag_minus2', 'tagesmitteltemperatur_tag_minus3', 'serie_minmax_tag_min_30d', 'serie_minmax_tag_max_30d', 'serie_minmax_tag_avg_30d', 'serie_verbrauch_tag_30d', 'serie_zaehlerstand_tag_30d', 'serie_tagesmittelwert_0d', 'serie_tagesmittelwert_stunde_0d', 'serie_tagesmittelwert_stunde_30_0d', 'serie_tagesmittelwert_tag_stunde_30d', 'kaeltesumme', 'waermesumme', 'gruenlandtempsumme', 'wachstumsgradtage', 'wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage', 'tagesmitteltemperatur'] -ONDEMAND_WEEKLY_ATTRIBUTES = ['verbrauch_woche_minus1', 'verbrauch_woche_minus2', 'verbrauch_woche_minus3', 'verbrauch_woche_minus4', 'verbrauch_rolling_12m_woche_minus1', 'zaehlerstand_woche_minus1', 'zaehlerstand_woche_minus2', 'zaehlerstand_woche_minus3', 'minmax_woche_minus1_min', 'minmax_woche_minus1_max', 'minmax_woche_minus1_avg', 'minmax_woche_minus2_min', 'minmax_woche_minus2_max', 'minmax_woche_minus2_avg', 'serie_minmax_woche_min_30w', 'serie_minmax_woche_max_30w', 'serie_minmax_woche_avg_30w', 'serie_verbrauch_woche_30w', 'serie_zaehlerstand_woche_30w'] -ONDEMAND_MONTHLY_ATTRIBUTES = ['verbrauch_monat_minus1', 'verbrauch_monat_minus2', 'verbrauch_monat_minus3', 'verbrauch_monat_minus4', 'verbrauch_monat_minus12', 'verbrauch_rolling_12m_monat_minus1', 'zaehlerstand_monat_minus1', 'zaehlerstand_monat_minus2', 'zaehlerstand_monat_minus3', 'minmax_monat_minus1_min', 'minmax_monat_minus1_max', 'minmax_monat_minus1_avg', 'minmax_monat_minus2_min', 'minmax_monat_minus2_max', 'minmax_monat_minus2_avg', 'serie_minmax_monat_min_15m', 'serie_minmax_monat_max_15m', 'serie_minmax_monat_avg_15m', 'serie_verbrauch_monat_18m', 'serie_zaehlerstand_monat_18m', 'serie_waermesumme_monat_24m', 'serie_kaeltesumme_monat_24m'] -ONDEMAND_YEARLY_ATTRIBUTES = ['verbrauch_jahr_minus1', 'verbrauch_jahr_minus2', 'verbrauch_jahr_minus3', 'verbrauch_rolling_12m_jahr_minus1', 'zaehlerstand_jahr_minus1', 'zaehlerstand_jahr_minus2', 'zaehlerstand_jahr_minus3', 'minmax_jahr_minus1_min', 'minmax_jahr_minus1_max', 'minmax_jahr_minus1_avg'] -ALL_HOURLY_ATTRIBUTES = ['verbrauch_last_24h', 'verbrauch_last_7d'] -ALL_DAILY_ATTRIBUTES = ['verbrauch_heute', 'verbrauch_tag', 'verbrauch_heute_minus1', 'verbrauch_heute_minus2', 'verbrauch_heute_minus3', 'verbrauch_heute_minus4', 'verbrauch_heute_minus5', 'verbrauch_heute_minus6', 'verbrauch_heute_minus7', 'verbrauch_heute_minus8', 'verbrauch_tag_minus1', 'verbrauch_tag_minus2', 'verbrauch_tag_minus3', 'verbrauch_tag_minus4', 'verbrauch_tag_minus5', 'verbrauch_tag_minus6', 'verbrauch_tag_minus7', 'verbrauch_tag_minus8', 'verbrauch_rolling_12m_heute_minus1', 'verbrauch_rolling_12m_tag_minus1', 'verbrauch_jahreszeitraum_minus1', 'verbrauch_jahreszeitraum_minus2', 'verbrauch_jahreszeitraum_minus3', 'zaehlerstand_heute_minus1', 'zaehlerstand_heute_minus2', 'zaehlerstand_heute_minus3', 'zaehlerstand_tag_minus1', 'zaehlerstand_tag_minus2', 'zaehlerstand_tag_minus3', 'minmax_last_24h_min', 'minmax_last_24h_max', 'minmax_last_24h_avg', 'minmax_last_7d_min', 'minmax_last_7d_max', 'minmax_last_7d_avg', 'minmax_heute_min', 'minmax_heute_max', 'minmax_heute_avg', 'minmax_heute_minus1_min', 'minmax_heute_minus1_max', 'minmax_heute_minus1_avg', 'minmax_heute_minus2_min', 'minmax_heute_minus2_max', 'minmax_heute_minus2_avg', 'minmax_heute_minus3_min', 'minmax_heute_minus3_max', 'minmax_heute_minus3_avg', 'minmax_tag_min', 'minmax_tag_max', 'minmax_tag_avg', 'minmax_tag_minus1_min', 'minmax_tag_minus1_max', 'minmax_tag_minus1_avg', 'minmax_tag_minus2_min', 'minmax_tag_minus2_max', 'minmax_tag_minus2_avg', 'minmax_tag_minus3_min', 'minmax_tag_minus3_max', 'minmax_tag_minus3_avg', 'tagesmitteltemperatur_heute', 'tagesmitteltemperatur_heute_minus1', 'tagesmitteltemperatur_heute_minus2', 'tagesmitteltemperatur_heute_minus3', 'tagesmitteltemperatur_tag', 'tagesmitteltemperatur_tag_minus1', 'tagesmitteltemperatur_tag_minus2', 'tagesmitteltemperatur_tag_minus3', 'serie_minmax_tag_min_30d', 'serie_minmax_tag_max_30d', 'serie_minmax_tag_avg_30d', 'serie_verbrauch_tag_30d', 'serie_zaehlerstand_tag_30d', 'serie_tagesmittelwert_0d', 'serie_tagesmittelwert_stunde_0d', 'serie_tagesmittelwert_stunde_30_0d', 'serie_tagesmittelwert_tag_stunde_30d', 'kaeltesumme', 'waermesumme', 'gruenlandtempsumme', 'wachstumsgradtage', 'wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage', 'tagesmitteltemperatur'] -ALL_WEEKLY_ATTRIBUTES = ['verbrauch_woche', 'verbrauch_woche_minus1', 'verbrauch_woche_minus2', 'verbrauch_woche_minus3', 'verbrauch_woche_minus4', 'verbrauch_rolling_12m_woche_minus1', 'zaehlerstand_woche_minus1', 'zaehlerstand_woche_minus2', 'zaehlerstand_woche_minus3', 'minmax_woche_min', 'minmax_woche_max', 'minmax_woche_minus1_min', 'minmax_woche_minus1_max', 'minmax_woche_minus1_avg', 'minmax_woche_minus2_min', 'minmax_woche_minus2_max', 'minmax_woche_minus2_avg', 'serie_minmax_woche_min_30w', 'serie_minmax_woche_max_30w', 'serie_minmax_woche_avg_30w', 'serie_verbrauch_woche_30w', 'serie_zaehlerstand_woche_30w'] -ALL_MONTHLY_ATTRIBUTES = ['verbrauch_monat', 'verbrauch_monat_minus1', 'verbrauch_monat_minus2', 'verbrauch_monat_minus3', 'verbrauch_monat_minus4', 'verbrauch_monat_minus12', 'verbrauch_rolling_12m_monat_minus1', 'zaehlerstand_monat_minus1', 'zaehlerstand_monat_minus2', 'zaehlerstand_monat_minus3', 'minmax_monat_min', 'minmax_monat_max', 'minmax_monat_minus1_min', 'minmax_monat_minus1_max', 'minmax_monat_minus1_avg', 'minmax_monat_minus2_min', 'minmax_monat_minus2_max', 'minmax_monat_minus2_avg', 'serie_minmax_monat_min_15m', 'serie_minmax_monat_max_15m', 'serie_minmax_monat_avg_15m', 'serie_verbrauch_monat_18m', 'serie_zaehlerstand_monat_18m', 'serie_waermesumme_monat_24m', 'serie_kaeltesumme_monat_24m'] -ALL_YEARLY_ATTRIBUTES = ['verbrauch_jahr', 'verbrauch_jahr_minus1', 'verbrauch_jahr_minus2', 'verbrauch_jahr_minus3', 'verbrauch_rolling_12m_jahr_minus1', 'zaehlerstand_jahr_minus1', 'zaehlerstand_jahr_minus2', 'zaehlerstand_jahr_minus3', 'minmax_jahr_min', 'minmax_jahr_max', 'minmax_jahr_minus1_min', 'minmax_jahr_minus1_max', 'minmax_jahr_minus1_avg'] -ALL_PARAMS_ATTRIBUTES = ['kaeltesumme', 'waermesumme', 'gruenlandtempsumme', 'wachstumsgradtage', 'wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage', 'tagesmitteltemperatur', 'db_request', 'minmax', 'minmax_last', 'verbrauch', 'zaehlerstand'] -ALL_VERBRAUCH_ATTRIBUTES = ['verbrauch_heute', 'verbrauch_tag', 'verbrauch_woche', 'verbrauch_monat', 'verbrauch_jahr', 'verbrauch_last_24h', 'verbrauch_last_7d', 'verbrauch_heute_minus1', 'verbrauch_heute_minus2', 'verbrauch_heute_minus3', 'verbrauch_heute_minus4', 'verbrauch_heute_minus5', 'verbrauch_heute_minus6', 'verbrauch_heute_minus7', 'verbrauch_heute_minus8', 'verbrauch_tag_minus1', 'verbrauch_tag_minus2', 'verbrauch_tag_minus3', 'verbrauch_tag_minus4', 'verbrauch_tag_minus5', 'verbrauch_tag_minus6', 'verbrauch_tag_minus7', 'verbrauch_tag_minus8', 'verbrauch_woche_minus1', 'verbrauch_woche_minus2', 'verbrauch_woche_minus3', 'verbrauch_woche_minus4', 'verbrauch_monat_minus1', 'verbrauch_monat_minus2', 'verbrauch_monat_minus3', 'verbrauch_monat_minus4', 'verbrauch_monat_minus12', 'verbrauch_jahr_minus1', 'verbrauch_jahr_minus2', 'verbrauch_jahr_minus3', 'verbrauch_rolling_12m_heute_minus1', 'verbrauch_rolling_12m_tag_minus1', 'verbrauch_rolling_12m_woche_minus1', 'verbrauch_rolling_12m_monat_minus1', 'verbrauch_rolling_12m_jahr_minus1', 'verbrauch_jahreszeitraum_minus1', 'verbrauch_jahreszeitraum_minus2', 'verbrauch_jahreszeitraum_minus3'] -VERBRAUCH_ATTRIBUTES_ONCHANGE = ['verbrauch_heute', 'verbrauch_tag', 'verbrauch_woche', 'verbrauch_monat', 'verbrauch_jahr'] -VERBRAUCH_ATTRIBUTES_TIMEFRAME = ['verbrauch_heute_minus1', 'verbrauch_heute_minus2', 'verbrauch_heute_minus3', 'verbrauch_heute_minus4', 'verbrauch_heute_minus5', 'verbrauch_heute_minus6', 'verbrauch_heute_minus7', 'verbrauch_heute_minus8', 'verbrauch_tag_minus1', 'verbrauch_tag_minus2', 'verbrauch_tag_minus3', 'verbrauch_tag_minus4', 'verbrauch_tag_minus5', 'verbrauch_tag_minus6', 'verbrauch_tag_minus7', 'verbrauch_tag_minus8', 'verbrauch_woche_minus1', 'verbrauch_woche_minus2', 'verbrauch_woche_minus3', 'verbrauch_woche_minus4', 'verbrauch_monat_minus1', 'verbrauch_monat_minus2', 'verbrauch_monat_minus3', 'verbrauch_monat_minus4', 'verbrauch_monat_minus12', 'verbrauch_jahr_minus1', 'verbrauch_jahr_minus2', 'verbrauch_jahr_minus3'] -VERBRAUCH_ATTRIBUTES_LAST = ['verbrauch_last_24h', 'verbrauch_last_7d'] -VERBRAUCH_ATTRIBUTES_ROLLING = ['verbrauch_rolling_12m_heute_minus1', 'verbrauch_rolling_12m_tag_minus1', 'verbrauch_rolling_12m_woche_minus1', 'verbrauch_rolling_12m_monat_minus1', 'verbrauch_rolling_12m_jahr_minus1'] -VERBRAUCH_ATTRIBUTES_JAHRESZEITRAUM = ['verbrauch_jahreszeitraum_minus1', 'verbrauch_jahreszeitraum_minus2', 'verbrauch_jahreszeitraum_minus3'] -ALL_ZAEHLERSTAND_ATTRIBUTES = ['zaehlerstand_heute_minus1', 'zaehlerstand_heute_minus2', 'zaehlerstand_heute_minus3', 'zaehlerstand_tag_minus1', 'zaehlerstand_tag_minus2', 'zaehlerstand_tag_minus3', 'zaehlerstand_woche_minus1', 'zaehlerstand_woche_minus2', 'zaehlerstand_woche_minus3', 'zaehlerstand_monat_minus1', 'zaehlerstand_monat_minus2', 'zaehlerstand_monat_minus3', 'zaehlerstand_jahr_minus1', 'zaehlerstand_jahr_minus2', 'zaehlerstand_jahr_minus3'] -ZAEHLERSTAND_ATTRIBUTES_TIMEFRAME = ['zaehlerstand_heute_minus1', 'zaehlerstand_heute_minus2', 'zaehlerstand_heute_minus3', 'zaehlerstand_tag_minus1', 'zaehlerstand_tag_minus2', 'zaehlerstand_tag_minus3', 'zaehlerstand_woche_minus1', 'zaehlerstand_woche_minus2', 'zaehlerstand_woche_minus3', 'zaehlerstand_monat_minus1', 'zaehlerstand_monat_minus2', 'zaehlerstand_monat_minus3', 'zaehlerstand_jahr_minus1', 'zaehlerstand_jahr_minus2', 'zaehlerstand_jahr_minus3'] -ALL_HISTORIE_ATTRIBUTES = ['minmax_last_24h_min', 'minmax_last_24h_max', 'minmax_last_24h_avg', 'minmax_last_7d_min', 'minmax_last_7d_max', 'minmax_last_7d_avg', 'minmax_heute_min', 'minmax_heute_max', 'minmax_heute_avg', 'minmax_heute_minus1_min', 'minmax_heute_minus1_max', 'minmax_heute_minus1_avg', 'minmax_heute_minus2_min', 'minmax_heute_minus2_max', 'minmax_heute_minus2_avg', 'minmax_heute_minus3_min', 'minmax_heute_minus3_max', 'minmax_heute_minus3_avg', 'minmax_tag_min', 'minmax_tag_max', 'minmax_tag_avg', 'minmax_tag_minus1_min', 'minmax_tag_minus1_max', 'minmax_tag_minus1_avg', 'minmax_tag_minus2_min', 'minmax_tag_minus2_max', 'minmax_tag_minus2_avg', 'minmax_tag_minus3_min', 'minmax_tag_minus3_max', 'minmax_tag_minus3_avg', 'minmax_woche_min', 'minmax_woche_max', 'minmax_woche_minus1_min', 'minmax_woche_minus1_max', 'minmax_woche_minus1_avg', 'minmax_woche_minus2_min', 'minmax_woche_minus2_max', 'minmax_woche_minus2_avg', 'minmax_monat_min', 'minmax_monat_max', 'minmax_monat_minus1_min', 'minmax_monat_minus1_max', 'minmax_monat_minus1_avg', 'minmax_monat_minus2_min', 'minmax_monat_minus2_max', 'minmax_monat_minus2_avg', 'minmax_jahr_min', 'minmax_jahr_max', 'minmax_jahr_minus1_min', 'minmax_jahr_minus1_max', 'minmax_jahr_minus1_avg'] -HISTORIE_ATTRIBUTES_ONCHANGE = ['minmax_heute_min', 'minmax_heute_max', 'minmax_heute_avg', 'minmax_tag_min', 'minmax_tag_max', 'minmax_tag_avg', 'minmax_woche_min', 'minmax_woche_max', 'minmax_monat_min', 'minmax_monat_max', 'minmax_jahr_min', 'minmax_jahr_max'] -HISTORIE_ATTRIBUTES_LAST = ['minmax_last_24h_min', 'minmax_last_24h_max', 'minmax_last_24h_avg', 'minmax_last_7d_min', 'minmax_last_7d_max', 'minmax_last_7d_avg'] -HISTORIE_ATTRIBUTES_TIMEFRAME = ['minmax_heute_minus1_min', 'minmax_heute_minus1_max', 'minmax_heute_minus1_avg', 'minmax_heute_minus2_min', 'minmax_heute_minus2_max', 'minmax_heute_minus2_avg', 'minmax_heute_minus3_min', 'minmax_heute_minus3_max', 'minmax_heute_minus3_avg', 'minmax_tag_minus1_min', 'minmax_tag_minus1_max', 'minmax_tag_minus1_avg', 'minmax_tag_minus2_min', 'minmax_tag_minus2_max', 'minmax_tag_minus2_avg', 'minmax_tag_minus3_min', 'minmax_tag_minus3_max', 'minmax_tag_minus3_avg', 'minmax_woche_minus1_min', 'minmax_woche_minus1_max', 'minmax_woche_minus1_avg', 'minmax_woche_minus2_min', 'minmax_woche_minus2_max', 'minmax_woche_minus2_avg', 'minmax_monat_minus1_min', 'minmax_monat_minus1_max', 'minmax_monat_minus1_avg', 'minmax_monat_minus2_min', 'minmax_monat_minus2_max', 'minmax_monat_minus2_avg', 'minmax_jahr_minus1_min', 'minmax_jahr_minus1_max', 'minmax_jahr_minus1_avg'] -ALL_TAGESMITTEL_ATTRIBUTES = ['tagesmitteltemperatur_heute', 'tagesmitteltemperatur_heute_minus1', 'tagesmitteltemperatur_heute_minus2', 'tagesmitteltemperatur_heute_minus3', 'tagesmitteltemperatur_tag', 'tagesmitteltemperatur_tag_minus1', 'tagesmitteltemperatur_tag_minus2', 'tagesmitteltemperatur_tag_minus3'] -TAGESMITTEL_ATTRIBUTES_ONCHANGE = ['tagesmitteltemperatur_heute', 'tagesmitteltemperatur_tag', 'minmax_heute_avg', 'minmax_tag_avg'] -TAGESMITTEL_ATTRIBUTES_TIMEFRAME = ['tagesmitteltemperatur_heute_minus1', 'tagesmitteltemperatur_heute_minus2', 'tagesmitteltemperatur_heute_minus3', 'tagesmitteltemperatur_tag_minus1', 'tagesmitteltemperatur_tag_minus2', 'tagesmitteltemperatur_tag_minus3'] -ALL_SERIE_ATTRIBUTES = ['serie_minmax_monat_min_15m', 'serie_minmax_monat_max_15m', 'serie_minmax_monat_avg_15m', 'serie_minmax_woche_min_30w', 'serie_minmax_woche_max_30w', 'serie_minmax_woche_avg_30w', 'serie_minmax_tag_min_30d', 'serie_minmax_tag_max_30d', 'serie_minmax_tag_avg_30d', 'serie_verbrauch_tag_30d', 'serie_verbrauch_woche_30w', 'serie_verbrauch_monat_18m', 'serie_zaehlerstand_tag_30d', 'serie_zaehlerstand_woche_30w', 'serie_zaehlerstand_monat_18m', 'serie_waermesumme_monat_24m', 'serie_kaeltesumme_monat_24m', 'serie_tagesmittelwert_0d', 'serie_tagesmittelwert_stunde_0d', 'serie_tagesmittelwert_stunde_30_0d', 'serie_tagesmittelwert_tag_stunde_30d'] -SERIE_ATTRIBUTES_MINMAX = ['serie_minmax_monat_min_15m', 'serie_minmax_monat_max_15m', 'serie_minmax_monat_avg_15m', 'serie_minmax_woche_min_30w', 'serie_minmax_woche_max_30w', 'serie_minmax_woche_avg_30w', 'serie_minmax_tag_min_30d', 'serie_minmax_tag_max_30d', 'serie_minmax_tag_avg_30d'] -SERIE_ATTRIBUTES_ZAEHLERSTAND = ['serie_zaehlerstand_tag_30d', 'serie_zaehlerstand_woche_30w', 'serie_zaehlerstand_monat_18m'] -SERIE_ATTRIBUTES_VERBRAUCH = ['serie_verbrauch_tag_30d', 'serie_verbrauch_woche_30w', 'serie_verbrauch_monat_18m'] -SERIE_ATTRIBUTES_SUMME = ['serie_waermesumme_monat_24m', 'serie_kaeltesumme_monat_24m'] -SERIE_ATTRIBUTES_MITTEL_D = ['serie_tagesmittelwert_0d'] -SERIE_ATTRIBUTES_MITTEL_H = ['serie_tagesmittelwert_stunde_0d'] -SERIE_ATTRIBUTES_MITTEL_H1 = ['serie_tagesmittelwert_stunde_30_0d'] -SERIE_ATTRIBUTES_MITTEL_D_H = ['serie_tagesmittelwert_tag_stunde_30d'] -ALL_GEN_ATTRIBUTES = ['general_oldest_value', 'general_oldest_log'] -ALL_SUMME_ATTRIBUTES = ['kaeltesumme', 'waermesumme', 'gruenlandtempsumme', 'wachstumsgradtage', 'wuestentage', 'heisse_tage', 'tropennaechte', 'sommertage', 'heiztage', 'vegetationstage', 'frosttage', 'eistage'] -ALL_COMPLEX_ATTRIBUTES = ['tagesmitteltemperatur', 'db_request', 'minmax', 'minmax_last', 'verbrauch', 'zaehlerstand'] diff --git a/db_addon/item_attributes_master.py b/db_addon/item_attributes_master.py index 2351f2812..142e21bf3 100644 --- a/db_addon/item_attributes_master.py +++ b/db_addon/item_attributes_master.py @@ -27,176 +27,178 @@ DOC_FILE_NAME = 'user_doc.rst' -PLUGIN_VERSION = '1.2.6' +PLUGIN_VERSION = '1.2.10' ITEM_ATTRIBUTES = { 'db_addon_fct': { - 'verbrauch_heute': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Verbrauch am heutigen Tag (Differenz zwischen aktuellem Wert und den Wert am Ende des vorherigen Tages)'}, - 'verbrauch_tag': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Verbrauch am heutigen Tag (Differenz zwischen aktuellem Wert und den Wert am Ende des vorherigen Tages)'}, - 'verbrauch_woche': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Verbrauch in der aktuellen Woche'}, - 'verbrauch_monat': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Verbrauch im aktuellen Monat'}, - 'verbrauch_jahr': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Verbrauch im aktuellen Jahr'}, - 'verbrauch_last_24h': {'cat': 'verbrauch', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'hourly', 'params': False, 'description': 'Verbrauch innerhalb letzten 24h'}, - 'verbrauch_last_7d': {'cat': 'verbrauch', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'hourly', 'params': False, 'description': 'Verbrauch innerhalb letzten 7 Tage'}, - 'verbrauch_heute_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch gestern (heute -1 Tag) (Differenz zwischen Wert am Ende des gestrigen Tages und dem Wert am Ende des Tages davor)'}, - 'verbrauch_heute_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch vorgestern (heute -2 Tage)'}, - 'verbrauch_heute_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -3 Tage'}, - 'verbrauch_heute_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -4 Tage'}, - 'verbrauch_heute_minus5': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -5 Tage'}, - 'verbrauch_heute_minus6': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -6 Tage'}, - 'verbrauch_heute_minus7': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -7 Tage'}, - 'verbrauch_heute_minus8': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -8 Tage'}, - 'verbrauch_tag_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch gestern (heute -1 Tag) (Differenz zwischen Wert am Ende des gestrigen Tages und dem Wert am Ende des Tages davor)'}, - 'verbrauch_tag_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch vorgestern (heute -2 Tage)'}, - 'verbrauch_tag_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -3 Tage'}, - 'verbrauch_tag_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -4 Tage'}, - 'verbrauch_tag_minus5': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -5 Tage'}, - 'verbrauch_tag_minus6': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -6 Tage'}, - 'verbrauch_tag_minus7': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -7 Tage'}, - 'verbrauch_tag_minus8': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch heute -8 Tage'}, - 'verbrauch_woche_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch Vorwoche (aktuelle Woche -1)'}, - 'verbrauch_woche_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch aktuelle Woche -2 Wochen'}, - 'verbrauch_woche_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch aktuelle Woche -3 Wochen'}, - 'verbrauch_woche_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch aktuelle Woche -4 Wochen'}, - 'verbrauch_monat_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch Vormonat (aktueller Monat -1)'}, - 'verbrauch_monat_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch aktueller Monat -2 Monate'}, - 'verbrauch_monat_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch aktueller Monat -3 Monate'}, - 'verbrauch_monat_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch aktueller Monat -4 Monate'}, - 'verbrauch_monat_minus12': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch aktueller Monat -12 Monate'}, - 'verbrauch_jahr_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Verbrauch Vorjahr (aktuelles Jahr -1 Jahr)'}, - 'verbrauch_jahr_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Verbrauch aktuelles Jahr -2 Jahre'}, - 'verbrauch_jahr_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Verbrauch aktuelles Jahr -3 Jahre'}, - 'verbrauch_rolling_12m_heute_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Tages'}, - 'verbrauch_rolling_12m_tag_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Tages'}, - 'verbrauch_rolling_12m_woche_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende der letzten Woche'}, - 'verbrauch_rolling_12m_monat_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Monats'}, - 'verbrauch_rolling_12m_jahr_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Jahres'}, - 'verbrauch_jahreszeitraum_minus1': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag des Vorjahres'}, - 'verbrauch_jahreszeitraum_minus2': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag vor 2 Jahren'}, - 'verbrauch_jahreszeitraum_minus3': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag vor 3 Jahren'}, - 'zaehlerstand_heute_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des letzten Tages (heute -1 Tag)'}, - 'zaehlerstand_heute_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorletzten Tages (heute -2 Tag)'}, - 'zaehlerstand_heute_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorvorletzten Tages (heute -3 Tag)'}, - 'zaehlerstand_tag_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des letzten Tages (heute -1 Tag)'}, - 'zaehlerstand_tag_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorletzten Tages (heute -2 Tag)'}, - 'zaehlerstand_tag_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorvorletzten Tages (heute -3 Tag)'}, - 'zaehlerstand_woche_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Zählerstand / Wert am Ende der vorvorletzten Woche (aktuelle Woche -1 Woche)'}, - 'zaehlerstand_woche_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Zählerstand / Wert am Ende der vorletzten Woche (aktuelle Woche -2 Wochen)'}, - 'zaehlerstand_woche_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Zählerstand / Wert am Ende der aktuellen Woche -3 Wochen'}, - 'zaehlerstand_monat_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Zählerstand / Wert am Ende des letzten Monates (aktueller Monat -1 Monat)'}, - 'zaehlerstand_monat_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorletzten Monates (aktueller Monat -2 Monate)'}, - 'zaehlerstand_monat_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Zählerstand / Wert am Ende des aktuellen Monats -3 Monate'}, - 'zaehlerstand_jahr_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Zählerstand / Wert am Ende des letzten Jahres (aktuelles Jahr -1 Jahr)'}, - 'zaehlerstand_jahr_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Zählerstand / Wert am Ende des vorletzten Jahres (aktuelles Jahr -2 Jahre)'}, - 'zaehlerstand_jahr_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Zählerstand / Wert am Ende des aktuellen Jahres -3 Jahre'}, - 'minmax_last_24h_min': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'minimaler Wert der letzten 24h'}, - 'minmax_last_24h_max': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'maximaler Wert der letzten 24h'}, - 'minmax_last_24h_avg': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'durchschnittlicher Wert der letzten 24h'}, - 'minmax_last_7d_min': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'minimaler Wert der letzten 7 Tage'}, - 'minmax_last_7d_max': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'maximaler Wert der letzten 7 Tage'}, - 'minmax_last_7d_avg': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'durchschnittlicher Wert der letzten 7 Tage'}, - 'minmax_heute_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Minimalwert seit Tagesbeginn'}, - 'minmax_heute_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Maximalwert seit Tagesbeginn'}, - 'minmax_heute_avg': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Durchschnittswert seit Tagesbeginn'}, - 'minmax_heute_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert gestern (heute -1 Tag)'}, - 'minmax_heute_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert gestern (heute -1 Tag)'}, - 'minmax_heute_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert gestern (heute -1 Tag)'}, - 'minmax_heute_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert vorgestern (heute -2 Tage)'}, - 'minmax_heute_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert vorgestern (heute -2 Tage)'}, - 'minmax_heute_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert vorgestern (heute -2 Tage)'}, - 'minmax_heute_minus3_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert heute vor 3 Tagen'}, - 'minmax_heute_minus3_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert heute vor 3 Tagen'}, - 'minmax_heute_minus3_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert heute vor 3 Tagen'}, - 'minmax_tag_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Minimalwert seit Tagesbeginn'}, - 'minmax_tag_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Maximalwert seit Tagesbeginn'}, - 'minmax_tag_avg': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Durchschnittswert seit Tagesbeginn'}, - 'minmax_tag_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert gestern (heute -1 Tag)'}, - 'minmax_tag_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert gestern (heute -1 Tag)'}, - 'minmax_tag_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert gestern (heute -1 Tag)'}, - 'minmax_tag_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert vorgestern (heute -2 Tage)'}, - 'minmax_tag_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert vorgestern (heute -2 Tage)'}, - 'minmax_tag_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert vorgestern (heute -2 Tage)'}, - 'minmax_tag_minus3_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Minimalwert heute vor 3 Tagen'}, - 'minmax_tag_minus3_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Maximalwert heute vor 3 Tagen'}, - 'minmax_tag_minus3_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Durchschnittswert heute vor 3 Tagen'}, - 'minmax_woche_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Minimalwert seit Wochenbeginn'}, - 'minmax_woche_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Maximalwert seit Wochenbeginn'}, - 'minmax_woche_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Minimalwert Vorwoche (aktuelle Woche -1)'}, - 'minmax_woche_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Maximalwert Vorwoche (aktuelle Woche -1)'}, - 'minmax_woche_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Durchschnittswert Vorwoche (aktuelle Woche -1)'}, - 'minmax_woche_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Minimalwert aktuelle Woche -2 Wochen'}, - 'minmax_woche_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Maximalwert aktuelle Woche -2 Wochen'}, - 'minmax_woche_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': False, 'description': 'Durchschnittswert aktuelle Woche -2 Wochen'}, - 'minmax_monat_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Minimalwert seit Monatsbeginn'}, - 'minmax_monat_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Maximalwert seit Monatsbeginn'}, - 'minmax_monat_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Minimalwert Vormonat (aktueller Monat -1)'}, - 'minmax_monat_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Maximalwert Vormonat (aktueller Monat -1)'}, - 'minmax_monat_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Durchschnittswert Vormonat (aktueller Monat -1)'}, - 'minmax_monat_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Minimalwert aktueller Monat -2 Monate'}, - 'minmax_monat_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Maximalwert aktueller Monat -2 Monate'}, - 'minmax_monat_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': False, 'description': 'Durchschnittswert aktueller Monat -2 Monate'}, - 'minmax_jahr_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Minimalwert seit Jahresbeginn'}, - 'minmax_jahr_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Maximalwert seit Jahresbeginn'}, - 'minmax_jahr_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Minimalwert Vorjahr (aktuelles Jahr -1 Jahr)'}, - 'minmax_jahr_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Maximalwert Vorjahr (aktuelles Jahr -1 Jahr)'}, - 'minmax_jahr_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': False, 'description': 'Durchschnittswert Vorjahr (aktuelles Jahr -1 Jahr)'}, - 'tagesmitteltemperatur_heute': {'cat': 'tagesmittel', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Tagesmitteltemperatur heute'}, - 'tagesmitteltemperatur_heute_minus1': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des letzten Tages (heute -1 Tag)'}, - 'tagesmitteltemperatur_heute_minus2': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des vorletzten Tages (heute -2 Tag)'}, - 'tagesmitteltemperatur_heute_minus3': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des vorvorletzten Tages (heute -3 Tag)'}, - 'tagesmitteltemperatur_tag': {'cat': 'tagesmittel', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Tagesmitteltemperatur heute'}, - 'tagesmitteltemperatur_tag_minus1': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des letzten Tages (heute -1 Tag)'}, - 'tagesmitteltemperatur_tag_minus2': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des vorletzten Tages (heute -2 Tag)'}, - 'tagesmitteltemperatur_tag_minus3': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': False, 'description': 'Tagesmitteltemperatur des vorvorletzten Tages (heute -3 Tag)'}, - 'serie_minmax_monat_min_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'monatlicher Minimalwert der letzten 15 Monate (gleitend)'}, - 'serie_minmax_monat_max_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'monatlicher Maximalwert der letzten 15 Monate (gleitend)'}, - 'serie_minmax_monat_avg_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'monatlicher Mittelwert der letzten 15 Monate (gleitend)'}, - 'serie_minmax_woche_min_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': False, 'description': 'wöchentlicher Minimalwert der letzten 30 Wochen (gleitend)'}, - 'serie_minmax_woche_max_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': False, 'description': 'wöchentlicher Maximalwert der letzten 30 Wochen (gleitend)'}, - 'serie_minmax_woche_avg_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': False, 'description': 'wöchentlicher Mittelwert der letzten 30 Wochen (gleitend)'}, - 'serie_minmax_tag_min_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'täglicher Minimalwert der letzten 30 Tage (gleitend)'}, - 'serie_minmax_tag_max_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'täglicher Maximalwert der letzten 30 Tage (gleitend)'}, - 'serie_minmax_tag_avg_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'täglicher Mittelwert der letzten 30 Tage (gleitend)'}, - 'serie_verbrauch_tag_30d': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Verbrauch pro Tag der letzten 30 Tage'}, - 'serie_verbrauch_woche_30w': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'weekly', 'params': False, 'description': 'Verbrauch pro Woche der letzten 30 Wochen'}, - 'serie_verbrauch_monat_18m': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'Verbrauch pro Monat der letzten 18 Monate'}, - 'serie_zaehlerstand_tag_30d': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Zählerstand am Tagesende der letzten 30 Tage'}, - 'serie_zaehlerstand_woche_30w': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'weekly', 'params': False, 'description': 'Zählerstand am Wochenende der letzten 30 Wochen'}, - 'serie_zaehlerstand_monat_18m': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'Zählerstand am Monatsende der letzten 18 Monate'}, - 'serie_waermesumme_monat_24m': {'cat': 'serie', 'sub_cat': 'summe', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'monatliche Wärmesumme der letzten 24 Monate'}, - 'serie_kaeltesumme_monat_24m': {'cat': 'serie', 'sub_cat': 'summe', 'item_type': 'list', 'cycle': 'monthly', 'params': False, 'description': 'monatliche Kältesumme der letzten 24 Monate'}, - 'serie_tagesmittelwert_0d': {'cat': 'serie', 'sub_cat': 'mittel_d', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Tagesmittelwert für den aktuellen Tag'}, - 'serie_tagesmittelwert_stunde_0d': {'cat': 'serie', 'sub_cat': 'mittel_h', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Stundenmittelwert für den aktuellen Tag'}, - 'serie_tagesmittelwert_stunde_30_0d': {'cat': 'serie', 'sub_cat': 'mittel_h1', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Stundenmittelwert für den aktuellen Tag'}, - 'serie_tagesmittelwert_tag_stunde_30d': {'cat': 'serie', 'sub_cat': 'mittel_d_h', 'item_type': 'list', 'cycle': 'daily', 'params': False, 'description': 'Stundenmittelwert pro Tag der letzten 30 Tage (bspw. zur Berechnung der Tagesmitteltemperatur basierend auf den Mittelwert der Temperatur pro Stunde'}, - 'general_oldest_value': {'cat': 'gen', 'sub_cat': None, 'item_type': 'num', 'cycle': None, 'params': False, 'description': 'Ausgabe des ältesten Wertes des entsprechenden "Parent-Items" mit database Attribut'}, - 'general_oldest_log': {'cat': 'gen', 'sub_cat': None, 'item_type': 'list', 'cycle': None, 'params': False, 'description': 'Ausgabe des Timestamp des ältesten Eintrages des entsprechenden "Parent-Items" mit database Attribut'}, - 'kaeltesumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Kältesumme für einen Zeitraum, db_addon_params: (year=optional, month=optional)'}, - 'waermesumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Wärmesumme für einen Zeitraum, db_addon_params: (year=optional, month=optional)'}, - 'gruenlandtempsumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Grünlandtemperatursumme für einen Zeitraum, db_addon_params: (year=optional)'}, - 'wachstumsgradtage': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Wachstumsgradtage auf Basis der stündlichen Durchschnittswerte eines Tages für das laufende Jahr mit an Angabe des Temperaturschwellenwertes (threshold=Schwellentemperatur)'}, - 'wuestentage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Wüstentage des Jahres, db_addon_params: (year=optional)'}, - 'heisse_tage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der heissen Tage des Jahres, db_addon_params: (year=optional)'}, - 'tropennaechte': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Tropennächte des Jahres, db_addon_params: (year=optional)'}, - 'sommertage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Sommertage des Jahres, db_addon_params: (year=optional)'}, - 'heiztage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Heiztage des Jahres, db_addon_params: (year=optional)'}, - 'vegetationstage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Vegatationstage des Jahres, db_addon_params: (year=optional)'}, - 'frosttage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Frosttage des Jahres, db_addon_params: (year=optional)'}, - 'eistage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Anzahl der Eistage des Jahres, db_addon_params: (year=optional)'}, - 'tagesmitteltemperatur': {'cat': 'complex', 'sub_cat': None, 'item_type': 'list', 'cycle': 'daily', 'params': True, 'description': 'Berechnet die Tagesmitteltemperatur auf Basis der stündlichen Durchschnittswerte eines Tages für die angegebene Anzahl von Tagen (timeframe=day, count=integer)'}, - 'db_request': {'cat': 'complex', 'sub_cat': None, 'item_type': 'list', 'cycle': 'group', 'params': True, 'description': 'Abfrage der DB: db_addon_params: (func=mandatory, item=mandatory, timespan=mandatory, start=optional, end=optional, count=optional, group=optional, group2=optional)'}, - 'minmax': {'cat': 'complex', 'sub_cat': None, 'item_type': 'num', 'cycle': 'timeframe', 'params': True, 'description': 'Berechnet einen min/max/avg Wert für einen bestimmen Zeitraum: db_addon_params: (func=mandatory, timeframe=mandatory, start=mandatory)'}, - 'minmax_last': {'cat': 'complex', 'sub_cat': None, 'item_type': 'num', 'cycle': 'timeframe', 'params': True, 'description': 'Berechnet einen min/max/avg Wert für ein bestimmtes Zeitfenster von jetzt zurück: db_addon_params: (func=mandatory, timeframe=mandatory, start=mandatory, end=mandatory)'}, - 'verbrauch': {'cat': 'complex', 'sub_cat': None, 'item_type': 'num', 'cycle': 'timeframe', 'params': True, 'description': 'Berechnet einen Verbrauchswert für einen bestimmen Zeitraum: db_addon_params: (timeframe=mandatory, start=mandatory end=mandatory)'}, - 'zaehlerstand': {'cat': 'complex', 'sub_cat': None, 'item_type': 'num', 'cycle': 'timeframe', 'params': True, 'description': 'Berechnet einen Zählerstand für einen bestimmen Zeitpunkt: db_addon_params: (timeframe=mandatory, start=mandatory)'}, + 'verbrauch_heute': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Verbrauch am heutigen Tag (Differenz zwischen aktuellem Wert und den Wert am Ende des vorherigen Tages)'}, + 'verbrauch_tag': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Verbrauch am heutigen Tag (Differenz zwischen aktuellem Wert und den Wert am Ende des vorherigen Tages)'}, + 'verbrauch_woche': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Verbrauch in der aktuellen Woche'}, + 'verbrauch_monat': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Verbrauch im aktuellen Monat'}, + 'verbrauch_jahr': {'cat': 'verbrauch', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Verbrauch im aktuellen Jahr'}, + 'verbrauch_last_24h': {'cat': 'verbrauch', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'hourly', 'params': None, 'description': 'Verbrauch innerhalb letzten 24h'}, + 'verbrauch_last_7d': {'cat': 'verbrauch', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'hourly', 'params': None, 'description': 'Verbrauch innerhalb letzten 7 Tage'}, + 'verbrauch_heute_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch gestern (heute -1 Tag) (Differenz zwischen Wert am Ende des gestrigen Tages und dem Wert am Ende des Tages davor)'}, + 'verbrauch_heute_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch vorgestern (heute -2 Tage)'}, + 'verbrauch_heute_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -3 Tage'}, + 'verbrauch_heute_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -4 Tage'}, + 'verbrauch_heute_minus5': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -5 Tage'}, + 'verbrauch_heute_minus6': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -6 Tage'}, + 'verbrauch_heute_minus7': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -7 Tage'}, + 'verbrauch_heute_minus8': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -8 Tage'}, + 'verbrauch_tag_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch gestern (heute -1 Tag) (Differenz zwischen Wert am Ende des gestrigen Tages und dem Wert am Ende des Tages davor)'}, + 'verbrauch_tag_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch vorgestern (heute -2 Tage)'}, + 'verbrauch_tag_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -3 Tage'}, + 'verbrauch_tag_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -4 Tage'}, + 'verbrauch_tag_minus5': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -5 Tage'}, + 'verbrauch_tag_minus6': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -6 Tage'}, + 'verbrauch_tag_minus7': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -7 Tage'}, + 'verbrauch_tag_minus8': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch heute -8 Tage'}, + 'verbrauch_woche_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch Vorwoche (aktuelle Woche -1)'}, + 'verbrauch_woche_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch aktuelle Woche -2 Wochen'}, + 'verbrauch_woche_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch aktuelle Woche -3 Wochen'}, + 'verbrauch_woche_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch aktuelle Woche -4 Wochen'}, + 'verbrauch_monat_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch Vormonat (aktueller Monat -1)'}, + 'verbrauch_monat_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch aktueller Monat -2 Monate'}, + 'verbrauch_monat_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch aktueller Monat -3 Monate'}, + 'verbrauch_monat_minus4': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch aktueller Monat -4 Monate'}, + 'verbrauch_monat_minus12': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch aktueller Monat -12 Monate'}, + 'verbrauch_jahr_minus1': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Verbrauch Vorjahr (aktuelles Jahr -1 Jahr)'}, + 'verbrauch_jahr_minus2': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Verbrauch aktuelles Jahr -2 Jahre'}, + 'verbrauch_jahr_minus3': {'cat': 'verbrauch', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Verbrauch aktuelles Jahr -3 Jahre'}, + 'verbrauch_rolling_12m_heute_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Tages'}, + 'verbrauch_rolling_12m_tag_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Tages'}, + 'verbrauch_rolling_12m_woche_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende der letzten Woche'}, + 'verbrauch_rolling_12m_monat_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Monats'}, + 'verbrauch_rolling_12m_jahr_minus1': {'cat': 'verbrauch', 'sub_cat': 'rolling', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Verbrauch der letzten 12 Monate ausgehend im Ende des letzten Jahres'}, + 'verbrauch_jahreszeitraum_minus1': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag des Vorjahres'}, + 'verbrauch_jahreszeitraum_minus2': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag vor 2 Jahren'}, + 'verbrauch_jahreszeitraum_minus3': {'cat': 'verbrauch', 'sub_cat': 'jahrzeit', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch seit dem 1.1. bis zum heutigen Tag vor 3 Jahren'}, + 'zaehlerstand_heute_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des letzten Tages (heute -1 Tag)'}, + 'zaehlerstand_heute_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorletzten Tages (heute -2 Tag)'}, + 'zaehlerstand_heute_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorvorletzten Tages (heute -3 Tag)'}, + 'zaehlerstand_tag_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des letzten Tages (heute -1 Tag)'}, + 'zaehlerstand_tag_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorletzten Tages (heute -2 Tag)'}, + 'zaehlerstand_tag_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorvorletzten Tages (heute -3 Tag)'}, + 'zaehlerstand_woche_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Zählerstand / Wert am Ende der vorvorletzten Woche (aktuelle Woche -1 Woche)'}, + 'zaehlerstand_woche_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Zählerstand / Wert am Ende der vorletzten Woche (aktuelle Woche -2 Wochen)'}, + 'zaehlerstand_woche_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Zählerstand / Wert am Ende der aktuellen Woche -3 Wochen'}, + 'zaehlerstand_monat_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Zählerstand / Wert am Ende des letzten Monates (aktueller Monat -1 Monat)'}, + 'zaehlerstand_monat_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorletzten Monates (aktueller Monat -2 Monate)'}, + 'zaehlerstand_monat_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Zählerstand / Wert am Ende des aktuellen Monats -3 Monate'}, + 'zaehlerstand_jahr_minus1': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Zählerstand / Wert am Ende des letzten Jahres (aktuelles Jahr -1 Jahr)'}, + 'zaehlerstand_jahr_minus2': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Zählerstand / Wert am Ende des vorletzten Jahres (aktuelles Jahr -2 Jahre)'}, + 'zaehlerstand_jahr_minus3': {'cat': 'zaehler', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Zählerstand / Wert am Ende des aktuellen Jahres -3 Jahre'}, + 'minmax_last_24h_min': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'minimaler Wert der letzten 24h'}, + 'minmax_last_24h_max': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'maximaler Wert der letzten 24h'}, + 'minmax_last_24h_avg': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'durchschnittlicher Wert der letzten 24h'}, + 'minmax_last_7d_min': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'minimaler Wert der letzten 7 Tage'}, + 'minmax_last_7d_max': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'maximaler Wert der letzten 7 Tage'}, + 'minmax_last_7d_avg': {'cat': 'wertehistorie', 'sub_cat': 'last', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'durchschnittlicher Wert der letzten 7 Tage'}, + 'minmax_heute_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Minimalwert seit Tagesbeginn'}, + 'minmax_heute_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Maximalwert seit Tagesbeginn'}, + 'minmax_heute_avg': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Durchschnittswert seit Tagesbeginn'}, + 'minmax_heute_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert gestern (heute -1 Tag)'}, + 'minmax_heute_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert gestern (heute -1 Tag)'}, + 'minmax_heute_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert gestern (heute -1 Tag)'}, + 'minmax_heute_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert vorgestern (heute -2 Tage)'}, + 'minmax_heute_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert vorgestern (heute -2 Tage)'}, + 'minmax_heute_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert vorgestern (heute -2 Tage)'}, + 'minmax_heute_minus3_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert heute vor 3 Tagen'}, + 'minmax_heute_minus3_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert heute vor 3 Tagen'}, + 'minmax_heute_minus3_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert heute vor 3 Tagen'}, + 'minmax_tag_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Minimalwert seit Tagesbeginn'}, + 'minmax_tag_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Maximalwert seit Tagesbeginn'}, + 'minmax_tag_avg': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Durchschnittswert seit Tagesbeginn'}, + 'minmax_tag_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert gestern (heute -1 Tag)'}, + 'minmax_tag_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert gestern (heute -1 Tag)'}, + 'minmax_tag_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert gestern (heute -1 Tag)'}, + 'minmax_tag_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert vorgestern (heute -2 Tage)'}, + 'minmax_tag_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert vorgestern (heute -2 Tage)'}, + 'minmax_tag_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert vorgestern (heute -2 Tage)'}, + 'minmax_tag_minus3_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Minimalwert heute vor 3 Tagen'}, + 'minmax_tag_minus3_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Maximalwert heute vor 3 Tagen'}, + 'minmax_tag_minus3_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Durchschnittswert heute vor 3 Tagen'}, + 'minmax_woche_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Minimalwert seit Wochenbeginn'}, + 'minmax_woche_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Maximalwert seit Wochenbeginn'}, + 'minmax_woche_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Minimalwert Vorwoche (aktuelle Woche -1)'}, + 'minmax_woche_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Maximalwert Vorwoche (aktuelle Woche -1)'}, + 'minmax_woche_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Durchschnittswert Vorwoche (aktuelle Woche -1)'}, + 'minmax_woche_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Minimalwert aktuelle Woche -2 Wochen'}, + 'minmax_woche_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Maximalwert aktuelle Woche -2 Wochen'}, + 'minmax_woche_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'weekly', 'params': None, 'description': 'Durchschnittswert aktuelle Woche -2 Wochen'}, + 'minmax_monat_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Minimalwert seit Monatsbeginn'}, + 'minmax_monat_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Maximalwert seit Monatsbeginn'}, + 'minmax_monat_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Minimalwert Vormonat (aktueller Monat -1)'}, + 'minmax_monat_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Maximalwert Vormonat (aktueller Monat -1)'}, + 'minmax_monat_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Durchschnittswert Vormonat (aktueller Monat -1)'}, + 'minmax_monat_minus2_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Minimalwert aktueller Monat -2 Monate'}, + 'minmax_monat_minus2_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Maximalwert aktueller Monat -2 Monate'}, + 'minmax_monat_minus2_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'monthly', 'params': None, 'description': 'Durchschnittswert aktueller Monat -2 Monate'}, + 'minmax_jahr_min': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Minimalwert seit Jahresbeginn'}, + 'minmax_jahr_max': {'cat': 'wertehistorie', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Maximalwert seit Jahresbeginn'}, + 'minmax_jahr_minus1_min': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Minimalwert Vorjahr (aktuelles Jahr -1 Jahr)'}, + 'minmax_jahr_minus1_max': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Maximalwert Vorjahr (aktuelles Jahr -1 Jahr)'}, + 'minmax_jahr_minus1_avg': {'cat': 'wertehistorie', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'yearly', 'params': None, 'description': 'Durchschnittswert Vorjahr (aktuelles Jahr -1 Jahr)'}, + 'tagesmitteltemperatur_heute': {'cat': 'tagesmittel', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Tagesmitteltemperatur heute'}, + 'tagesmitteltemperatur_heute_minus1': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des letzten Tages (heute -1 Tag)'}, + 'tagesmitteltemperatur_heute_minus2': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des vorletzten Tages (heute -2 Tag)'}, + 'tagesmitteltemperatur_heute_minus3': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des vorvorletzten Tages (heute -3 Tag)'}, + 'tagesmitteltemperatur_tag': {'cat': 'tagesmittel', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Tagesmitteltemperatur heute'}, + 'tagesmitteltemperatur_tag_minus1': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des letzten Tages (heute -1 Tag)'}, + 'tagesmitteltemperatur_tag_minus2': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des vorletzten Tages (heute -2 Tag)'}, + 'tagesmitteltemperatur_tag_minus3': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmitteltemperatur des vorvorletzten Tages (heute -3 Tag)'}, + 'tagesmittelwert_tag': {'cat': 'tagesmittel', 'sub_cat': 'onchange', 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Tagesmittelwert heute'}, + 'tagesmittelwert_tag_minus1': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmittelwert des letzten Tages (heute -1 Tag)'}, + 'tagesmittelwert_tag_minus2': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmittelwert des vorletzten Tages (heute -2 Tag)'}, + 'tagesmittelwert_tag_minus3': {'cat': 'tagesmittel', 'sub_cat': 'timeframe', 'item_type': 'num', 'cycle': 'daily', 'params': None, 'description': 'Tagesmittelwert des vorvorletzten Tages (heute -3 Tag)'}, + 'serie_minmax_monat_min_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'monatlicher Minimalwert der letzten 15 Monate (gleitend)'}, + 'serie_minmax_monat_max_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'monatlicher Maximalwert der letzten 15 Monate (gleitend)'}, + 'serie_minmax_monat_avg_15m': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'monatlicher Mittelwert der letzten 15 Monate (gleitend)'}, + 'serie_minmax_woche_min_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': None, 'description': 'wöchentlicher Minimalwert der letzten 30 Wochen (gleitend)'}, + 'serie_minmax_woche_max_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': None, 'description': 'wöchentlicher Maximalwert der letzten 30 Wochen (gleitend)'}, + 'serie_minmax_woche_avg_30w': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'weekly', 'params': None, 'description': 'wöchentlicher Mittelwert der letzten 30 Wochen (gleitend)'}, + 'serie_minmax_tag_min_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'täglicher Minimalwert der letzten 30 Tage (gleitend)'}, + 'serie_minmax_tag_max_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'täglicher Maximalwert der letzten 30 Tage (gleitend)'}, + 'serie_minmax_tag_avg_30d': {'cat': 'serie', 'sub_cat': 'minmax', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'täglicher Mittelwert der letzten 30 Tage (gleitend)'}, + 'serie_verbrauch_tag_30d': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Verbrauch pro Tag der letzten 30 Tage'}, + 'serie_verbrauch_woche_30w': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'weekly', 'params': None, 'description': 'Verbrauch pro Woche der letzten 30 Wochen'}, + 'serie_verbrauch_monat_18m': {'cat': 'serie', 'sub_cat': 'verbrauch', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'Verbrauch pro Monat der letzten 18 Monate'}, + 'serie_zaehlerstand_tag_30d': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Zählerstand am Tagesende der letzten 30 Tage'}, + 'serie_zaehlerstand_woche_30w': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'weekly', 'params': None, 'description': 'Zählerstand am Wochenende der letzten 30 Wochen'}, + 'serie_zaehlerstand_monat_18m': {'cat': 'serie', 'sub_cat': 'zaehler', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'Zählerstand am Monatsende der letzten 18 Monate'}, + 'serie_waermesumme_monat_24m': {'cat': 'serie', 'sub_cat': 'summe', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'monatliche Wärmesumme der letzten 24 Monate'}, + 'serie_kaeltesumme_monat_24m': {'cat': 'serie', 'sub_cat': 'summe', 'item_type': 'list', 'cycle': 'monthly', 'params': None, 'description': 'monatliche Kältesumme der letzten 24 Monate'}, + 'serie_tagesmittelwert_0d': {'cat': 'serie', 'sub_cat': 'mittel_d', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Tagesmittelwert für den aktuellen Tag'}, + 'serie_tagesmittelwert_stunde_0d': {'cat': 'serie', 'sub_cat': 'mittel_h', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Stundenmittelwert für den aktuellen Tag'}, + 'serie_tagesmittelwert_stunde_30_0d': {'cat': 'serie', 'sub_cat': 'mittel_h1', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Stundenmittelwert für den aktuellen Tag'}, + 'serie_tagesmittelwert_tag_stunde_30d': {'cat': 'serie', 'sub_cat': 'mittel_d_h', 'item_type': 'list', 'cycle': 'daily', 'params': None, 'description': 'Stundenmittelwert pro Tag der letzten 30 Tage (bspw. zur Berechnung der Tagesmitteltemperatur basierend auf den Mittelwert der Temperatur pro Stunde'}, + 'general_oldest_value': {'cat': 'gen', 'sub_cat': None, 'item_type': 'num', 'cycle': None, 'params': None, 'description': 'Ausgabe des ältesten Wertes des entsprechenden "Parent-Items" mit database Attribut'}, + 'general_oldest_log': {'cat': 'gen', 'sub_cat': None, 'item_type': 'list', 'cycle': None, 'params': None, 'description': 'Ausgabe des Timestamp des ältesten Eintrages des entsprechenden "Parent-Items" mit database Attribut'}, + 'kaeltesumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month', 'result'], {}), 'description': 'Berechnet die Kältesumme für einen Zeitraum, db_addon_params: (year=optional, month=optional, ignore_value_list=optional, result=optional)'}, + 'waermesumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month', 'threshold', 'result'], {}), 'description': 'Berechnet die Wärmesumme für einen Zeitraum, db_addon_params: (year=optional, month=optional, ignore_value_list=optional, threshold=optional, result=optional)'}, + 'gruenlandtempsumme': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month', 'result'], {}), 'description': 'Berechnet die Grünlandtemperatursumme für einen Zeitraum, db_addon_params: (year=optional, ignore_value_list=optional, result=optional)'}, + 'wachstumsgradtage': {'cat': 'summe', 'sub_cat': None, 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month', 'threshold', 'result'], {}), 'description': 'Berechnet die Wachstumsgradtage auf Basis der stündlichen Durchschnittswerte eines Tages für das laufende Jahr mit an Angabe des Temperaturschwellenwertes, db_addon_params: (year=optional, ignore_value_list=optional, variant=optional, threshold=optional, result=optional)'}, + 'wuestentage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Wüstentage des Jahres, db_addon_params: (year=optional)'}, + 'heisse_tage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der heissen Tage des Jahres, db_addon_params: (year=optional)'}, + 'tropennaechte': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Tropennächte des Jahres, db_addon_params: (year=optional)'}, + 'sommertage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Sommertage des Jahres, db_addon_params: (year=optional)'}, + 'heiztage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Heiztage des Jahres, db_addon_params: (year=optional)'}, + 'vegetationstage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Vegatationstage des Jahres, db_addon_params: (year=optional)'}, + 'frosttage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Frosttage des Jahres, db_addon_params: (year=optional)'}, + 'eistage': {'cat': 'summe', 'sub_cat': 'kenntage', 'item_type': 'num', 'cycle': 'daily', 'params': ([], ['year', 'month'], {}), 'description': 'Berechnet die Anzahl der Eistage des Jahres, db_addon_params: (year=optional)'}, + 'tagesmittelwert': {'cat': 'tagesmittel', 'sub_cat': 'complex', 'item_type': 'list', 'cycle': 'daily', 'params': (['timeframe', 'start', 'end'], [], {'data_con_func': 'avg_hour'}), 'description': 'Berechnet die Tagesmittelwert auf Basis der stündlichen Durchschnittswerte eines Tages für die angegebene Anzahl von Tagen (timeframe=day, count=integer)'}, + 'db_request': {'cat': 'complex', 'sub_cat': None, 'item_type': 'list', 'cycle': 'group', 'params': (['func', 'timeframe'], ['start', 'end', 'group', 'group2', 'ignore_value_list', 'use_oldest_entry'], {}), 'description': 'Abfrage der DB: db_addon_params: (func=mandatory, item=mandatory, timespan=mandatory, start=optional, end=optional, count=optional, group=optional, group2=optional)'}, + 'minmax': {'cat': 'wertehistorie', 'sub_cat': 'complex', 'item_type': 'num', 'cycle': 'timeframe', 'params': (['func', 'timeframe', 'start'], ['end'], {}), 'description': 'Ermittelt einen min/max/avg Wert für einen bestimmen Zeitraum: db_addon_params: (func=mandatory, timeframe=mandatory, start=mandatory, end=optional)'}, + 'verbrauch': {'cat': 'verbrauch', 'sub_cat': 'complex', 'item_type': 'num', 'cycle': 'timeframe', 'params': (['timeframe', 'start', 'end'], [], {}), 'description': 'Berechnet einen Verbrauchswert für einen bestimmen Zeitraum: db_addon_params: (timeframe=mandatory, start=mandatory end=mandatory)'}, + 'zaehlerstand': {'cat': 'zaehler', 'sub_cat': 'complex', 'item_type': 'num', 'cycle': 'timeframe', 'params': (['timeframe', 'start'], [], {}), 'description': 'Ermittelt einen Zählerstand für einen bestimmen Zeitpunkt: db_addon_params: (timeframe=mandatory, start=mandatory)'}, }, 'db_addon_info': { - 'db_version': {'cat': 'info', 'item_type': 'str', 'cycle': None, 'params': False, 'description': 'Version der verbundenen Datenbank'}, + 'db_version': {'cat': 'info', 'sub_cat': None, 'item_type': 'str', 'cycle': None, 'params': None, 'description': 'Version der verbundenen Datenbank'}, }, 'db_addon_admin': { - 'suspend': {'cat': 'admin', 'item_type': 'bool', 'cycle': None, 'params': False, 'description': 'Unterbricht die Aktivitäten des Plugin'}, - 'recalc_all': {'cat': 'admin', 'item_type': 'bool', 'cycle': None, 'params': False, 'description': 'Startet einen Neuberechnungslauf aller on-demand Items'}, - 'clean_cache_values': {'cat': 'admin', 'item_type': 'bool', 'cycle': None, 'params': False, 'description': 'Löscht Plugin-Cache und damit alle im Plugin zwischengespeicherten Werte'}, + 'recalc_all': {'cat': 'admin', 'sub_cat': None, 'item_type': 'bool', 'cycle': None, 'params': None, 'description': 'Startet einen Neuberechnungslauf aller on-demand Items'}, + 'clean_cache_values': {'cat': 'admin', 'sub_cat': None, 'item_type': 'bool', 'cycle': None, 'params': None, 'description': 'Löscht Plugin-Cache und damit alle im Plugin zwischengespeicherten Werte'}, }, } @@ -246,26 +248,16 @@ def get_attrs(sub_dict: dict = {}) -> list: def export_item_attributes_py(): print() - print(f"A) Start generation of {FILENAME_ATTRIBUTES}") + print(f"## Start generation of {FILENAME_ATTRIBUTES}") ATTRS = dict() - ATTRS['ONCHANGE_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change'}) - ATTRS['ONCHANGE_HOURLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change', 'calc': 'hourly'}) - ATTRS['ONCHANGE_DAILY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change', 'calc': 'daily'}) - ATTRS['ONCHANGE_WEEKLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change', 'calc': 'weekly'}) - ATTRS['ONCHANGE_MONTHLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change', 'calc': 'monthly'}) - ATTRS['ONCHANGE_YEARLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'change', 'calc': 'yearly'}) - ATTRS['ONDEMAND_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand'}) - ATTRS['ONDEMAND_HOURLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand', 'calc': 'hourly'}) - ATTRS['ONDEMAND_DAILY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand', 'calc': 'daily'}) - ATTRS['ONDEMAND_WEEKLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand', 'calc': 'weekly'}) - ATTRS['ONDEMAND_MONTHLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand', 'calc': 'monthly'}) - ATTRS['ONDEMAND_YEARLY_ATTRIBUTES'] = get_attrs(sub_dict={'on': 'demand', 'calc': 'yearly'}) - ATTRS['ALL_HOURLY_ATTRIBUTES'] = get_attrs(sub_dict={'calc': 'hourly'}) - ATTRS['ALL_DAILY_ATTRIBUTES'] = get_attrs(sub_dict={'calc': 'daily'}) - ATTRS['ALL_WEEKLY_ATTRIBUTES'] = get_attrs(sub_dict={'calc': 'weekly'}) - ATTRS['ALL_MONTHLY_ATTRIBUTES'] = get_attrs(sub_dict={'calc': 'monthly'}) - ATTRS['ALL_YEARLY_ATTRIBUTES'] = get_attrs(sub_dict={'calc': 'yearly'}) + ATTRS['ONCHANGE_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': None}) + ATTRS['ONDEMAND_HOURLY_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': 'hourly'}) + ATTRS['ONDEMAND_DAILY_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': 'daily'}) + ATTRS['ONDEMAND_WEEKLY_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': 'weekly'}) + ATTRS['ONDEMAND_MONTHLY_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': 'monthly'}) + ATTRS['ONDEMAND_YEARLY_ATTRIBUTES'] = get_attrs(sub_dict={'cycle': 'yearly'}) + ATTRS['ONDEMAND_ATTRIBUTES'] = ATTRS['ONDEMAND_HOURLY_ATTRIBUTES'] + ATTRS['ONDEMAND_DAILY_ATTRIBUTES'] + ATTRS['ONDEMAND_WEEKLY_ATTRIBUTES'] + ATTRS['ONDEMAND_MONTHLY_ATTRIBUTES'] + ATTRS['ONDEMAND_YEARLY_ATTRIBUTES'] ATTRS['ALL_PARAMS_ATTRIBUTES'] = get_attrs(sub_dict={'params': True}) ATTRS['ALL_VERBRAUCH_ATTRIBUTES'] = get_attrs(sub_dict={'cat': 'verbrauch'}) ATTRS['VERBRAUCH_ATTRIBUTES_ONCHANGE'] = get_attrs(sub_dict={'cat': 'verbrauch', 'sub_cat': 'onchange'}) @@ -331,8 +323,11 @@ def create_plugin_yaml_item_attribute_valids(attribute): valid_list_item_type = f"""{valid_list_item_type}\n\ - '{ITEM_ATTRIBUTES[attribute][db_addon_fct]['item_type']:<}'""" + cycle = ITEM_ATTRIBUTES[attribute][db_addon_fct]['cycle'] + if not cycle: + cycle = "" valid_list_calculation = f"""{valid_list_calculation}\n\ - - '{ITEM_ATTRIBUTES[attribute][db_addon_fct]['calc']:<}'""" + - '{cycle:<}'""" valid_list_calculation = f"""{valid_list_calculation}\n\r""" @@ -343,7 +338,7 @@ def update_plugin_yaml_item_attributes(): """Update 'valid_list', 'valid_list_description', 'valid_list_item_type' and 'valid_list_calculation' of item attributes in plugin.yaml""" print() - print(f"B) Start updating valid for attributes in {FILENAME_PLUGIN}") + print(f"## Start updating valid for attributes in {FILENAME_PLUGIN}") for attribute in ITEM_ATTRIBUTES: @@ -376,7 +371,7 @@ def update_plugin_yaml_item_attributes(): def check_plugin_yaml_structs(): # check structs for wrong attributes print() - print(f'C) Checking used attributes in structs defined in {FILENAME_PLUGIN} ') + print(f'## Checking used attributes in structs defined in {FILENAME_PLUGIN} ') # open plugin.yaml and update yaml = ruamel.yaml.YAML() @@ -413,7 +408,7 @@ def get_all_keys(d): def update_user_doc(): # Update user_doc.rst print() - print(f'D) Start updating DB-Addon-Attributes and descriptions in {DOC_FILE_NAME}!"') + print(f'## Start updating DB-Addon-Attributes and descriptions in {DOC_FILE_NAME}!"') attribute_list = [ "Dieses Kapitel wurde automatisch durch Ausführen des Skripts in der Datei 'item_attributes_master.py' erstellt.\n", "\n", "Nachfolgend eine Auflistung der möglichen Attribute für das Plugin im Format: Attribute: Beschreibung | Berechnungszyklus | Item-Type\n", @@ -428,7 +423,7 @@ def update_user_doc(): for db_addon_fct in ITEM_ATTRIBUTES[attribute]: attribute_list.append(f"- {db_addon_fct}: {ITEM_ATTRIBUTES[attribute][db_addon_fct]['description']} " - f"| Berechnung: {ITEM_ATTRIBUTES[attribute][db_addon_fct]['calc']} " + f"| Berechnung: {ITEM_ATTRIBUTES[attribute][db_addon_fct]['cycle']} " f"| Item-Type: {ITEM_ATTRIBUTES[attribute][db_addon_fct]['item_type']}\n") attribute_list.append("\n") @@ -437,9 +432,9 @@ def update_user_doc(): start = end = None for i, line in enumerate(lines): - if 'db_addon Item-Attribute' in line: + if 'Verfügbare Item-Attribute' in line: start = i + 3 - if 'Hinweise' in line: + if 'Beispiele für vordefinierte Auswertungen' in line: end = i - 1 part1 = lines[0:start] @@ -450,7 +445,7 @@ def update_user_doc(): for line in new_lines: file.write(line) - print(f" Successfully updated Foshk-Attributes in {DOC_FILE_NAME}!") + print(f" Successfully updated DB-Addon-Attributes in {DOC_FILE_NAME}!") if __name__ == '__main__': @@ -458,7 +453,7 @@ def update_user_doc(): print(f'Start automated update and check of {FILENAME_PLUGIN} with generation of {FILENAME_ATTRIBUTES} and update of {DOC_FILE_NAME}.') print('-------------------------------------------------------------') - export_item_attributes_py() + # export_item_attributes_py() update_plugin_yaml_item_attributes() diff --git a/db_addon/plugin.yaml b/db_addon/plugin.yaml index 53a0f836a..be58ae85c 100644 --- a/db_addon/plugin.yaml +++ b/db_addon/plugin.yaml @@ -11,10 +11,10 @@ plugin: # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1848494-support-thread-databaseaddon-plugin - version: 1.2.9 # Plugin version (must match the version specified in __init__.py) + version: 1.2.10 # Plugin version (must match the version specified in __init__.py) sh_minversion: 1.9.3.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) - py_minversion: '3.8' # minimum Python version to use for this plugin + py_minversion: '3.9' # minimum Python version to use for this plugin # py_maxversion: # maximum Python version to use for this plugin (leave empty if latest) multi_instance: false # plugin supports multi instance restartable: unknown @@ -69,6 +69,13 @@ parameters: de: Sperren der Datenbank während der Abfrage en: Lock the database during queries + pause_item: + type: str + default: '' + description: + de: 'Item, um die Ausführung des Plugins zu steuern' + en: 'item for controlling plugin execution' + item_attributes: db_addon_fct: type: str diff --git a/db_addon/webif/__init__.py b/db_addon/webif/__init__.py index 79c76ca57..bff423039 100644 --- a/db_addon/webif/__init__.py +++ b/db_addon/webif/__init__.py @@ -86,13 +86,13 @@ def index(self, reload=None, action=None, item_path=None, active=None, option=No return tmpl.render(p=self.plugin, webif_pagelength=pagelength, - suspended='true' if self.plugin.suspended else 'false', items=self.plugin.get_item_list('db_addon', 'function'), item_count=len(self.plugin.get_item_list('db_addon', 'function')), plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), plugin_info=self.plugin.get_info(), maintenance=True if self.plugin.log_level < 20 else False, + paused=not(self.plugin.alive) ) @cherrypy.expose @@ -116,7 +116,6 @@ def get_data_html(self, dataSet=None): data['items'][item.property.path]['last_update'] = item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') data['items'][item.property.path]['last_change'] = item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') - data['plugin_suspended'] = self.plugin.suspended data['maintenance'] = True if self.plugin.log_level == 10 else False data['queue_length'] = self.plugin.queue_backlog() data['active_queue_item'] = self.plugin.active_queue_item @@ -149,12 +148,15 @@ def submit(self, item=None): self.logger.debug(f"Result for web interface: {result}") return json.dumps(result).encode('utf-8') - elif cmd.startswith("suspend_plugin_calculation"): - self.logger.debug(f"set_plugin_calculation {cmd=}") + elif cmd.startswith("pause_plugin"): + self.logger.debug(f"pause_plugin {cmd=}") cmd, value = cmd.split(',') - value = True if value == "True" else False - self.logger.info(f"Plugin will be set to suspended: {value} via WebIF.") - result = self.plugin.suspend(value) + if value == "True": + self.plugin.stop() + else: + self.plugin.run() + self.logger.warning(f"Plugin will be set to paused: {value} via WebIF.") + result = not(self.plugin.alive) self.logger.debug(f"Result for web interface: {result}") return json.dumps(result).encode('utf-8') @@ -187,16 +189,6 @@ def clear_queue(self): self.logger.debug(f"_clear_queue called") self.plugin._clear_queue() - @cherrypy.expose - def activate(self): - self.logger.debug(f"active called") - self.plugin.suspend(False) - - @cherrypy.expose - def suspend(self): - self.logger.debug(f"suspend called") - self.plugin.suspend(True) - @cherrypy.expose def debug_log_option(self, log: str = None, state: bool = None): self.logger.warning(f"debug_log_option called with {log=}, {state=}") diff --git a/db_addon/webif/templates/index.html b/db_addon/webif/templates/index.html index 270751ff7..c7da035df 100644 --- a/db_addon/webif/templates/index.html +++ b/db_addon/webif/templates/index.html @@ -68,17 +68,17 @@ {% block pluginscripts %}