Mit SmartHomeNG existiert bereits eine Reihe zeitbezogener Daten über Shtime.get_instance().now()
. Speziell für Datenbankabfragen kann es aber hilfreich sein, noch einige Zusatzitems zu haben. Diese werden im Rahmen dieses Artikels gezeigt.
Die Items
date:
month:
since:
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.month.since.year
eval: str(sh.date.month.since.year()) + 'm'
until:
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.month.until.year
eval: str(sh.date.month.until.year()) + 'm'
week:
since:
month:
type: num
cache: 'yes'
year:
type: num
cache: 'yes'
until:
month:
type: num
cache: 'yes'
year:
type: num
cache: 'yes'
day:
since:
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.since.week
eval: str(sh.date.day.since.week()) + 'd'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.since.month
eval: str(sh.date.day.since.month()) + 'd'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.since.year
eval: str(sh.date.day.since.year()) + 'd'
until:
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.since.week
eval: str(sh.date.day.since.week()) + 'd'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.until.month
eval: str(sh.date.day.until.month()) + 'd'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.day.until.year
eval: str(sh.date.day.until.year()) + 'd'
hour:
since:
midnight:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.since.midnight
eval: str(sh.date.hour.since.midnight()) + 'h'
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.since.week
eval: str(sh.date.hour.since.week()) + 'h'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.since.month
eval: str(sh.date.hour.since.month()) + 'h'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.since.year
eval: str(sh.date.hour.since.year()) + 'h'
until:
midnight:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.until.midnight
eval: str(sh.date.hour.until.midnight()) + 'h'
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.until.week
eval: str(sh.date.hour.until.week()) + 'h'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.until.month
eval: str(sh.date.hour.until.month()) + 'h'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.hour.until.year
eval: str(sh.date.hour.until.year()) + 'h'
minute:
since:
hour:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.since.hour
eval: str(sh.date.minute.since.hour()) + 'i'
midnight:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.since.midnight
eval: str(sh.date.minute.since.midnight()) + 'i'
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.since.week
eval: str(sh.date.minute.since.week()) + 'i'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.since.month
eval: str(sh.date.minute.since.month()) + 'i'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.since.year
eval: str(sh.date.minute.since.year()) + 'i'
until:
hour:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.until.hour
eval: str(sh.date.minute.until.hour()) + 'i'
midnight:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.until.midnight
eval: str(sh.date.minute.until.midnight()) + 'i'
week:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.until.week
eval: str(sh.date.minute.until.week()) + 'i'
month:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.until.month
eval: str(sh.date.minute.until.month()) + 'i'
year:
type: num
cache: 'yes'
dbstr:
type: str
cache: 'yes'
eval_trigger: date.minute.until.year
eval: str(sh.date.minute.until.year()) + 'i'
second:
since:
minute:
type: num
hour:
type: num
midnight:
type: num
week:
type: num
month:
type: num
year:
type: num
until:
minute:
type: num
hour:
type: num
midnight:
type: num
week:
type: num
month:
type: num
year:
type: num
Die Logik
Als Logik wird unter logics/zeit.py
die nachfolgende Datei angelegt.
# /logics/zeit.py
# !/usr/bin/env python3
from lib.shtime import Shtime
sh_now = Shtime.get_instance().now()
# Funktionen
def days_of_month(month, year):
if month in [1, 3, 5, 7, 8, 10, 12]:
days = 31
elif month in [4, 6, 9, 11]:
days = 30
elif (year % 400 == 0) or ((year % 4 == 0) and not (year % 100 == 0)): # Schaltjahr
days = 29
else:
days = 28
return days
def days_of_year(year):
period_end = datetime.datetime(year, 12, 31)
days_of_year = (period_end - datetime.datetime(period_end.year, 1, 1)).days + 1
return (days_of_year)
def day_of_year(year, month, day):
period_end = datetime.datetime(year, month, day)
day_of_year = (period_end - datetime.datetime(period_end.year, 1, 1)).days + 1
return (day_of_year)
# Sekunde/Minute
sh.date.second.since.minute(sh_now.second)
sh.date.second.until.minute(60 - sh_now.second - 1)
# Minute/Stunde
sh.date.minute.since.hour(sh_now.minute)
sh.date.minute.until.hour(60 - sh_now.minute - 1)
# Stunde/Tag
sh.date.hour.since.midnight(sh_now.hour)
sh.date.hour.until.midnight(24 - sh_now.hour - 1)
# Tag/Woche
sh.date.day.since.week(sh_now.isoweekday())
sh.date.day.until.week(7 - sh_now.isoweekday())
# Stunde/Woche
sh.date.hour.since.week(sh.date.hour.since.midnight() + (24 * (sh.date.day.since.week() - 1)))
sh.date.hour.until.week(sh.date.hour.until.midnight() + (24 * sh.date.day.until.week()))
# Kalenderwoche/Jahr
sh.date.week.since.year(sh_now.isocalendar()[1])
sh.date.week.until.year(52-sh_now.isocalendar()[1])
# Monat/Jahr
sh.date.month.since.year(sh_now.month)
sh.date.month.until.year(12 - sh_now.month)
# Sekunde/Stunde
sh.date.second.since.hour(sh.date.second.since.minute() + (60 * sh.date.minute.since.hour()))
sh.date.second.until.hour(sh.date.second.until.minute() + (60 * sh.date.minute.until.hour()))
# Sekunde/Tag
sh.date.second.since.midnight(sh.date.second.since.minute() + (3600 * sh.date.hour.since.midnight()))
sh.date.second.until.midnight(sh.date.second.until.minute() + (3600 * sh.date.hour.until.midnight()))
# Minute/Tag
sh.date.minute.since.midnight(sh.date.minute.since.hour() + (60 * sh.date.hour.since.midnight()))
sh.date.minute.until.midnight(sh.date.minute.until.hour() + (60 * sh.date.hour.until.midnight()))
# Minute/Woche
sh.date.minute.since.week(sh.date.minute.since.hour() + (60 * sh.date.hour.since.week()))
sh.date.minute.until.week(sh.date.minute.until.hour() + (60 * sh.date.hour.until.week()))
# Sekunde/Woche
sh.date.second.since.week(sh.date.second.since.minute() + (60 * sh.date.minute.since.week()))
sh.date.second.until.week(sh.date.second.until.minute() + (60 * sh.date.minute.until.week()))
# Tage/Monat
sh.date.day.since.month(sh_now.day)
sh.date.day.until.month(days_of_month(sh_now.month, sh_now.year) - sh.date.day.since.month() - 1)
# Wochen/Monat
sh.date.week.since.month((sh.date.day.since.month()-1)//7+1)
sh.date.week.until.month((sh.date.day.until.month())//7)
# Tage/Jahr
sh.date.day.since.year(day_of_year(sh_now.year, sh_now.month, sh_now.day) - 1)
sh.date.day.until.year(days_of_year(sh_now.year) - sh.date.day.since.year() - 1)
# Stunde/Monat
sh.date.hour.since.month((24 * sh.date.day.since.month()) + sh.date.hour.since.midnight())
sh.date.hour.until.month((24 * days_of_month(sh_now.month, sh_now.year)) - sh.date.hour.since.month() - 1)
# Stunde/Jahr
sh.date.hour.since.year((24 * sh.date.day.since.year()) + sh.date.hour.since.midnight())
sh.date.hour.until.year((24 * days_of_year(sh_now.year)) - sh.date.hour.since.year() - 1)
# Minute/Monat
sh.date.minute.since.month((60 * sh.date.hour.since.month()) + sh.date.minute.since.hour())
sh.date.minute.until.month(sh.date.minute.since.month() - (60 * sh.date.hour.until.month()) - 1)
# Minute/Jahr
sh.date.minute.since.year((60 * sh.date.hour.since.year()) + sh.date.minute.since.hour())
sh.date.minute.until.year((60 * sh.date.hour.until.year()) + sh.date.minute.until.hour())
# Sekunde/Monat
sh.date.second.since.month((60 * sh.date.minute.since.month()) + sh.date.second.since.minute())
sh.date.second.until.month((60 * sh.date.minute.until.month()) + sh.date.second.until.minute())
# Sekunde/Jahr
sh.date.second.since.year((60 * sh.date.minute.since.year()) + sh.date.second.since.minute())
sh.date.second.until.year((60 * sh.date.minute.until.year()) + sh.date.second.until.minute())
In der etc/logic.yaml
wird sie wie folgt eingebunden:
zeitberechnung:
filename: zeit.py
crontab:
- init
- '* * * *'
Anwendungsbeispiel: Database Plugin
Neben der Anzeige der Daten, macht es vor allem Sinn, die Werte im Zusammenspiel mit (historischen) Datenbank-Daten zu verwenden. Ein Beispiel wäre wie folgt:
consumption_since_midnight:
type: num
eval: sh.knx.cellar.utility_room.water_meter.db('count>0', sh.date.minute.since.midnight.dbstr(), 'now')
eval_trigger: knx.cellar.utility_room.water_meter
database@mysqldb: init
Im Eval-Ausdruck wird die Anzahl der Werte > 0 ermittelt, die zwischen Mitternacht und dem IST-Zeitpunkt erfasst wurden. Da für 1 Liter jedes Mal ein Impuls mit einer „1“ erfasst wird, erhält man so minutengenau die Anzahl der Liter seit Mitternacht. Die Methode dbstr()
in sh.date.minute.since.midnight.dbstr()
liefert direkt den Wert, den das Database-Plugin benötigt. Präziser gesagt, hängt sie dem numerischen Wert
Über die Methode .db
auf dem Item, wird die Datenbankabfrage gestartet. Das Item muss dazu mit dem Database-Plugin verknüpft sein database@mysqldb: init
und bereits Daten im abgefragten Zeitraum erfasst haben.
(Das Titelbild ist unter der Creative Commons Zero (CC0) Lizenz veröffentlicht und wurde von www.pexels.com bezogen.)
3 Kommentare
Marc René Frieß · 3. Mai 2018 um 17:21
Ich habe mir das jetzt angeschaut und sehe noch nicht so recht den Verwendungszweck Deiner zusätzlichen Items?
Die Beispiele im 2ten Post sind ok, die aber alle in den Artikel aufzunehmen und zu erklären bläht den Inhalt ziemlich auf und verwirrt eher..
Die lasse ich auch mal als Kommentar. Ist ja legitim.
Ich habe mir zudem erlaubt Deine Kommentare zu formatieren. Der interessierte Leser kann sich die ja dann im Nachgang „einverleiben“.
Bitte in Zukunft selber machen.
sisamiwe · 2. Mai 2018 um 20:26
Bei der Abfrage bzw. Berechnung von Verbrauchsdaten hätte ich auch noch ein Beispiel.
Ich ermittle des Heizölverbrauch über die Einschaltzeit des Brenners (via einem KNX-Binäreingang). Die Logik dahinter ist einfach: Der Brenner braucht 2l pro Betriebsstunde. Die Einschaltzeit des Brenners wird ermittelt und in die DB geschrieben. Der jeweiligen Verbrauchswerte werden aus den DB-Werten ermittelt.
Hier meine Items:
Interessant?
sisamiwe · 2. Mai 2018 um 20:20
Hi,
ich habe das auch so in Verwendung.
Um bei Verbrauchsangaben den richtigen Monat zu haben, habe ich die Logik im folgende Punkte ergänzt:
und die Items:
GGf. kannst Du das ergänzen
Michael