Skip to content

Commit

Permalink
Merge pull request #605 from onkelandy/log_text
Browse files Browse the repository at this point in the history
lib.item: Improve and extend log_text / log_rules for item logging
  • Loading branch information
msinn authored Dec 20, 2023
2 parents 0e88f0a + 01e5209 commit 2e85d81
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 24 deletions.
77 changes: 63 additions & 14 deletions doc/user/source/referenz/items/standard_attribute/log_change.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,24 @@ Unterstützt werden folgende Variablen/Platzhalter:
+-----------------+------------------------------------------------------------------------------+
| {pid} | ID (Pfad) des Parent-Items |
+-----------------+------------------------------------------------------------------------------+
| {lowlimit} | unterer Grenzwert für Logeinträge |
| {lowlimit} | unterer Grenzwert für Logeinträge aus dem ``log_rules`` Attribut |
+-----------------+------------------------------------------------------------------------------+
| {highlimit} | oberer Grenzwert für Logeinträge |
| {highlimit} | oberer Grenzwert für Logeinträge aus dem ``log_rules`` Attribut |
+-----------------+------------------------------------------------------------------------------+
| {stamp} | aktueller UNIX Zeitstempel |
+-----------------+------------------------------------------------------------------------------+
| {time} | aktuelle Uhrzeit im Format HH:MM:SS |
+-----------------+------------------------------------------------------------------------------+
| {date} | aktuelles Datum im Format DD.MM.YYYY |
+-----------------+------------------------------------------------------------------------------+
| {now} | aktuelle Zeit im Format von sh.now (YYYY-MM-DD HH:MM:SS.ss+TZ) |
+-----------------+------------------------------------------------------------------------------+
| {itemvalue} | der Wert eines Items (z.B, ein Text) aus dem ``log_rules`` Attribut |
+-----------------+------------------------------------------------------------------------------+
| {filter} | der aktuell aktive (positive) Filter |
+-----------------+------------------------------------------------------------------------------+
| {exclude} | der aktuell aktive negative Filter |
+-----------------+------------------------------------------------------------------------------+


eval-Ausdrücke in log_text
--------------------------
Expand All @@ -112,7 +125,7 @@ Attribut *log_mapping*
Über das **log_mapping** Attribut kann festgelegt werden, auf welche Werte/Strings der Wert eines Items für das
Logging gemappt werden soll. Das Attribut **log_mapping** enthält dazu in einem String die Beschreibung eines
dicts. Wobei der Key den zu übersetzenden/mappenden Wert angibt und der dazu gehörige Value des dicts den String
angeibt, der über die Variable ``{mvalue}`` ausgegeben wird.
angibt, der über die Variable ``{mvalue}`` ausgegeben wird.

**Beispiel:**

Expand All @@ -135,20 +148,38 @@ anzuwenden sind. Das Attribut **log_rules** enthält dazu in einem String die Be

.. code-block:: yaml
log_rules: "{
'lowlimit' : -1.0,
'highlimit': 10.0,
'filter': [1, 2, 5]
}"
item:
type: num
log_rules: "{
'lowlimit' : -1.0,
'highlimit': 10.0,
'filter': [1, 2, 5],
'exclude': '.exclude_values',
'itemvalue': '.text'
}"
exclude_values:
type: list
initial_value: [2, 10]
cache: True
text:
type: str
initial_value: 'This is the log message'
cache: True
Die Filter Liste hat dabei vorrang. Es wird also nur bei den Werten 1, 2 und 5 geloggt, obwohl lowlimit und
highlimit weitere Werte zulassen würden.
Die Filter Liste hat dabei Vorrang. Es wird also nur bei den Werten 1, 2 und 5 geloggt, obwohl lowlimit und
highlimit weitere Werte zulassen würden bzw. exclude einen der Werte ausschließen würde.

.. hint::

Sämtliche Werte in den log_rules können ab SmartHomeNG 1.10 auch in Items hinterlegt werden.
Der Verweis auf das jeweilige Item erfolgt dabei durch den absoluten oder relativen Itempfad als String (ohne sh.).

lowlimit
--------

``lowlimit`` ein Wert der angibt, unterhalb welchen Wertes des Items **kein** Logeintrag geschrieben werden soll.
``lowlimit`` Ein Wert, der angibt, unterhalb welchen Wertes des Items **kein** Logeintrag geschrieben werden soll.
Werte werden geschrieben, Wenn **lowlimit** <= **value** ist.

**low_limit** kann nur auf Items vom Typ **num** angewendet werden.
Expand All @@ -157,7 +188,7 @@ Werte werden geschrieben, Wenn **lowlimit** <= **value** ist.
highlimit
---------

``highlimit`` ein Wert der angibt, oberhalb welchen Wertes des Items **kein** Logeintrag geschrieben werden soll.
``highlimit`` Ein Wert, der angibt, oberhalb welchen Wertes des Items **kein** Logeintrag geschrieben werden soll.
Werte werden geschrieben, Wenn **value** < **highlimit** ist.

**highlimit** kann nur auf Items vom Typ **num** angewendet werden.
Expand All @@ -166,8 +197,26 @@ Werte werden geschrieben, Wenn **value** < **highlimit** ist.
filter
------

``filter`` eine Werteliste die angibt, bei welchen Werten des Items ein Logeintrag geschrieben werden soll.
``filter`` Eine Werteliste, die angibt, bei welchen Werten des Items ein Logeintrag geschrieben werden soll.

Wenn das Item vom Typ **num** ist, muss die Liste auch numerische Werte (int oder float) enthalten
(``'filter': [1, 2, 5, 2.1]``). Falls das Item von einem anderen Datentyp ist, muss die Liste Strings
enthalten (``'filter': ['1', '2', '5']``).


exclude
-------

``exclude`` Eine Werteliste, die angibt, bei welchen Werten des Items ein Logeintrag nicht geschrieben werden soll.

Wenn das Item vom Typ **num** ist, muss die Liste auch numerische Werte (int oder float) enthalten
(``'exclude': [1, 2, 5, 2.1]``). Falls das Item von einem anderen Datentyp ist, muss die Liste Strings
enthalten (``'exclude': ['1', '2', '5']``).


itemvalue
---------

``itemvalue`` Der absolute oder relative Pfad zu einem Item, dessen Wert ausgelesen werden soll.
Dies kann beispielsweise dazu genutzt werden, die Lognachricht zur Laufzeit anzupassen.

85 changes: 75 additions & 10 deletions lib/item/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -2018,17 +2018,39 @@ def _log_build_text(self, value, caller, source=None, dest=None):
mlvalue = self._log_mapping.get(lvalue, lvalue)
name = self._name
age = round(self._get_last_change_age(), 2)
pname = self.__parent._name
id = self._path
pid = self.__parent._path
if self.__parent = _items_instance:

This comment has been minimized.

Copy link
@msinn

msinn Dec 20, 2023

Author Member

Du hast den Code nie bei Dir laufen lassen, oder???

pname = None
pid = None
else:
pname = self.__parent._name
pid = self.__parent._path
mvalue = self._log_mapping.get(value, value)
lowlimit = self._log_rules.get('lowlimit', None)
highlimit = self._log_rules.get('highlimit', None)

lowlimit = self._get_rule('lowlimit')
highlimit = self._get_rule('highlimit')
filter = self._get_rule('filter')
exclude = self._get_rule('exclude')

sh = self._sh
shtime = self.shtime
time = shtime.now().strftime("%H:%M:%S")
date = shtime.now().strftime("%d.%m.%Y")
stamp = shtime.now().timestamp()
now = str(shtime.now())

items = _items_instance
try:
entry = self._log_rules.get('itemvalue', None)
if entry is not None:
item = self.get_absolutepath(entry.strip().replace("sh.", ""), "log_rules")
itemvalue = str(_items_instance.return_item(item).property.value)
else:
itemvalue = None
except Exception as e:
logger.error(f"{id}: Invalid item in log_text '{self._log_text}'"
f" or log_rules '{self._log_rules}' - (Exception: {e})")
itemvalue = "INVALID"

import math
import lib.userfunctions as uf
env = lib.env
Expand All @@ -2042,30 +2064,73 @@ def _log_build_text(self, value, caller, source=None, dest=None):
return txt


def _get_rule(self, rule_entry):
def convert_entry(entry, to):
returnvalue = entry
if isinstance(returnvalue, str) and to != "str":
try:
# try to get value from item
item = self.get_absolutepath(entry.strip().replace("sh.", ""), "log_rules")
returnvalue = _items_instance.return_item(item).property.value
except Exception as e:
pass
if isinstance(returnvalue, (str, int)) and to == "num":
try:
returnvalue = float(returnvalue)
except ValueError as e:
returnvalue = None
elif isinstance(entry, list):
entry = [convert_entry(val, self._type) for val in entry]
elif isinstance(returnvalue, (float, int)) and to == "str":
returnvalue = str(returnvalue)
if returnvalue is None:
logger.warning(f"Given log_rules entry '{entry}' is invalid.")
return returnvalue

defaults = {'filter': [], 'exclude': [], 'lowlimit': None, 'highlimit': None}
types = {'filter': 'list', 'exclude': 'list', 'lowlimit': 'num', 'highlimit': 'num'}
entry = self._log_rules.get(rule_entry, defaults.get(rule_entry))
if entry is not None and entry != []:
entry = convert_entry(entry, types.get(rule_entry) or self._type)

return entry

def _log_on_change(self, value, caller, source=None, dest=None):
"""
Write log, if Item has attribute log_change set
:return:
"""

if self._log_change_logger is not None:
filter_list = self._log_rules.get('filter', [])
filter_list = self._get_rule('filter')
exclude_list = self._get_rule('exclude')
if filter_list != [] and exclude_list != []:
logger.warning(f"Defining filter AND exclude does not work. "
f"Ignoring exclude list {exclude_list} "
f"Using filter: {filter_list}")

if self._type == 'num':
low_limit = self._log_rules.get('lowlimit', None)
if low_limit:
low_limit = self._get_rule('lowlimit')
if low_limit is not None:
if low_limit > float(value):
return
high_limit = self._log_rules.get('highlimit', None)
if high_limit:
high_limit = self._get_rule('highlimit')
if high_limit is not None:
if high_limit <= float(value):
return
if filter_list != []:
if not float(value) in filter_list:
return
elif exclude_list != []:
if float(value) in exclude_list:
return
else:
if filter_list != []:
if not value in filter_list:
return
elif exclude_list != []:
if value in exclude_list:
return

if self._log_text is None:
txt = self._log_build_standardtext(value, caller, source, dest)
Expand Down

0 comments on commit 2e85d81

Please sign in to comment.