HourCounter: Unterschied zwischen den Versionen
John (Diskussion | Beiträge) |
John (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
Zeile 1: | Zeile 1: | ||
{{Infobox Modul | {{Infobox Modul | ||
|ModPurpose=HourCounter dient zum Zählen von Ereignissen und zur Erfassung von | |ModPurpose=HourCounter dient zum Zählen von Ereignissen und zur Erfassung von Betriebs-/Ruhe-Zeiten | ||
|ModType=h | |ModType=h | ||
<!-- |ModCmdRef=LightScene -- nicht erforderlich, da Modultyp x --> | <!-- |ModCmdRef=LightScene -- nicht erforderlich, da Modultyp x --> |
Version vom 23. Oktober 2014, 21:09 Uhr
HourCounter | |
---|---|
Zweck / Funktion | |
HourCounter dient zum Zählen von Ereignissen und zur Erfassung von Betriebs-/Ruhe-Zeiten | |
Allgemein | |
Typ | Hilfsmodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | Codeschnipsel |
Modulname | 98_HourCounter.pm |
Ersteller | John (Forum / Wiki) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
HourCounter ist ein Perl-Modul, das die Anzahl von Ereignissen erfasst. Bei bipolaren Ereignissen wird zusätzlich die Puls- sowie die Pausendauer ermittelt. Im vorliegenden Beispiel wird ein Betriebsstundenzähler mit einem MAX-Fensterkontakt realisiert.
Features
- Ermittlung von Betriebsstunden, Auslastung, Verbräuchen, Schalthäufigkeiten
- Ermittlung der Häufigkeit, Puls- Pausendauer pro Tag
- Ermittlung der Puls-/Pausendauer der letzten Schaltperiode
- Bereitstellung von Ereignissen zur Fortführung der Kumulation für Tages-, Wochen- und Monatswerte
- unterstützende Funktionen zur Ablage von Tages-, Wochen- und Monatswerten
Zielsetzung des WIKI-Artikels
Erläuterung der Funktionalität zur weiterführenden Diskussion im Forum.
Aktuelle Version
Das Modul ist seit dem 24.10.2014 Bestandteil von FHEM.
Definition
Abstrakt
define <name> HourCounter <regexp_for_ON> [<regexp_for_Off>]
<regexp_for_ON> ist ein regulärer Ausdruck der das Ereignis beschreibt.
Wenn auch [<regexp_for_Off>] definiert ist, so sprechen wir von einem bipolarem Ereignis, das einen EIN- sowie einen AUS-Zustand aufweist.
<regexp_for_ON> beschreibt in diesem Fall die positive Flanke,[<regexp_for_Off>] die negative Flanke. Die Struktur des regexp-Ausdruckes ist analog zu jener beim Notify aufgebaut.
Konkret
define CN.Test HourCounter SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0
Hier wird der HourCounter CN.TEST definiert. Ein MAX-Fensterkontakt mit Namen SHUTTER.JOHN wird als Ereignis-Geber verwendet. Das Reading "onoff" wird als Trigger für unserem Zähler genutzt. Bei den Fensterkontakten sehen diese Ereignisse wie folgt aus:
2013-11-15 23:19:12 MAX SHUTTER.JOHN onoff: 1 .... 2013-11-15 23:19:24 MAX SHUTTER.JOHN onoff: 0
Soll ein Dummy als Ereignis-Geber verwendet werden, lautet die Definition wie folgt:
define CN.Test HourCounter myDummy:1 myDummy:0
Die neue Instanz weist folgende Struktur auf:
Internals: CFGFN DEF SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0 NAME CN.Test NR 738 NTFY_ORDER 50-CN.Test STATE 1 TYPE HourCounter Readings: 2014-02-04 20:59:22 clearDate 2014-02-04 20:59:22 2014-02-04 20:59:57 countsOverall 1 2014-02-04 20:59:57 countsPerDay 1 2014-02-04 20:59:57 pauseTimeIncrement 35 2014-02-04 20:59:57 pauseTimeOverall 35 2014-02-04 20:59:57 pauseTimePerDay 35 2014-02-04 21:00:01 pulseTimeIncrement 4 2014-02-04 21:00:01 pulseTimeOverall 4 2014-02-04 21:00:01 pulseTimePerDay 4 2014-02-04 20:59:57 state 1 2014-02-04 21:00:00 tickHour 1 2014-02-04 21:00:01 value 0 Helper: OFF_Regexp SHUTTER.JOHN:onoff:.0 ON_Regexp SHUTTER.JOHN:onoff:.1 calledByEvent changedTimestamp 2014-02-04 21:00:01 forceClear forceDayChange forceHourChange forceMonthChange forceWeekChange isFirstRun sdRoundHourLast 1391544000 value 0 cmdQueue:
Readings
Reading | Beschreibung |
---|---|
clearDate | Datum, zu dem alle kumulativen Readings über set .. clear gelöscht wurden |
countsOverall | Absolutzähler für das Auftreten des ON-Ereignisses |
countsPerDay | Tageszähler für das Auftreten des ON-Ereignisses |
pauseTimeIncrement | Zeitdauer in Sekunden der Pause-Phase der letzten Periode |
pauseTimeOverall | Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen |
pauseTimePerDay | Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen des akt. Tages |
pulseTimeIncrement | Zeitdauer in Sekunden der Puls-Phase der letzten Periode |
pulseTimeOverall | Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen |
pulseTimePerDay | Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen des akt. Tages |
value | Aktueller Schaltzustand gemäss ON/OFF Ereignis,mit 1=letztes Ereignis war ON-Ereignis |
tickDay | Event wird nach Tageswechsel gefeuert bevor die Tageszähler resettiert werden |
tickHour | Event wird nach Stundenwechsel gefeuert |
tickWeek | Event wird nach Wochenwechsel gefeuert |
tickMonth | Event wird nach Monatswechsel gefeuert |
tickYear | Event wird nach Jahreswechsel gefeuert |
forceHourChange | simuliert einen Stundenwechsel |
forceDayChange | simuliert einen Tageswechsel |
forceWeekChange | simuliert einen Wochenwechsel |
forceMonthChange | simuliert einen Monatswechsel |
forceYearChange | simuliert einen Jahreswechsel |
Web-Oberfläche
Anwendung
Nachfolgende Darstellung zeigt das Einschaltverhalten eines Heizungskessels zusammen mit den abgeleiteten Werten.
- die Kurve "Brenner EIN" zeigt die Trigger-Signale des ON/OFF Filters, also das Ein-/Ausschalten des Brenners
- die Kurve "Brenner-Starts" zeigt die über den Tag aufgelaufenen Starts, also chronologisch das Anwachsen von Reading countsPerDay
- die Kurve "Betriebsstunden" zeigt die aufgelaufene Zeit aus dem Reading pulseTimePerDay umgerechnet zu Stunden
- die Kurve "Dauer" zeigt die Dauer des letzten Pulses in Sekunden
- die Kurve Auslastung zeigt das Verhältnis des Readings pulseTimePerDay zur seit Tagesbeginn vergangenen Zeit.
Chart der Aktualwerte
Wir benötigen hierzu ein File-Archiv für die aufgelaufenen Daten.
define CN.Test.File FileLog ./log/CN.Test-%Y.log (CN\.Test:.*)
Man erhält nach den ersten Ereignissen Einträge in folgender Form:
2013-11-16_12:45:40 CN.Test value: 1 2013-11-16_12:45:40 CN.Test 1 2013-11-16_12:46:21 CN.Test pulseTimeIncrement: 41 2013-11-16_12:46:21 CN.Test pulseTimePerDay: 41 2013-11-16_12:46:21 CN.Test pulseTimeOverall: 41 2013-11-16_12:46:21 CN.Test value: 0 2013-11-16_12:50:38 CN.Test countsPerDay: 2 2013-11-16_12:50:38 CN.Test countsOverall: 2 2013-11-16_12:50:38 CN.Test pauseTimeIncrement: 257 2013-11-16_12:50:38 CN.Test pauseTimePerDay: 756 2013-11-16_12:50:38 CN.Test pauseTimeOverall: 756 2013-11-16_12:50:38 CN.Test value: 1 2013-11-16_12:50:38 CN.Test 2
Nun kann man den Chart definieren:
Für die Kurve "Brenner EIN" verwenden wir CN.Test.value. Damit diese als unterste Kurve dargestellt wird transformieren wir den Wert 1 auf -2 und alle anderen (also die 0) auf -21 mit folgender Funktion:
$fld[3]=~"1"?-2:-19
Die "Brenner Starts" können wir direkt von countsPerDay ableiten.
Für die "Betriebsstunden" verwenden wir pulseTimePerDay. Da diese in Sekunden vorliegen teilen wir den Wert durch 3600, um Stunden zu erhalten.
$fld[3]/=3600
Als letzten versorgen wir noch die Kurve "Dauer" mit pulseTimeIncrement. Da wir diese in Minuten haben wollen ist ebenfalls eine Umformung nötig.
$fld[3]/=60
Somit sind die Basis-Kurven angelegt.
Erweiterungen
Es wurden im Forum viele Wünsche formuliert, weitere Funktionalitäten für den HourCounter einzuführen.
- Aggregation über bestimmte oder ganz freie Zeiträume
- komplexe Berechnungen, die zum Verbrauch führen
- Zuordnung von Verbräuchen zu unterschiedlichen Countern nach bestimmten Bedingungen
Vor allem die Aggregation erfasster Werte in Stunden-, Tages-, Wochen- und Monatswerten ist eine sinnvolle Erweiterung bei der Verbrauchserfassung.
HourCounter bietet Schnittstellen an, die es ermöglichen, das Modul selbst mit neuen Eigenschaften zu erweitern.
Die Referenz-Implementierung in 99_UtilsHourCounter.pm zeigt, wie dies skript-technisch zu realisieren ist.
Installation
99_UtilsHourCounter aus dem Verzeichnis "contrib" ist in das Verzeichnis der Module zu kopieren (beim Raspberry Pi /opt/fhem/FHEM).
Readings
99_UtilsHourCounter erweitert den HourCounter um folgende Funktionen:
Reading | Beschreibung |
---|---|
appCountsPerHour | Stundenzähler, wird bei Stundenwechsel aktualisiert |
appCountsPerHourTemp | Arbeitszähler zu appCountsPerHour |
appCountsPerDay | Tageszähler, wird bei Tageswechsel aktualisiert (Arbeitszähler ist countsPerDay) |
appCountsPerWeek | Wochenzähler, wird bei Wochenwechsel aktualisiert |
appCountsPerWeekTemp | Arbeitszähler zu appCountsPerWeek |
appCountsPerMonth | Monatszähler, wird bei Monatswechsel aktualisiert |
appCountsPerMonthTemp | Arbeitszähler zu appCountsPerMonth |
appCountsPerYear | Jahreszähler, wird bei Jahreswechsel aktualisiert |
appCountsPerYearTemp | Arbeitszähler zu appCountsPerYear |
appOpHoursPerDay | Betriebsstunden des Tages |
appOpHoursPerDayTemp | Arbeitszähler zu appOpHoursPerDay |
appOpHoursPerWeek | Betriebsstunden der Woche |
appOpHoursPerWeekTemp | Arbeitszähler zu appOpHoursPerWeek |
appOpHoursPerMonth | Betriebsstunden des Monats |
appOpHoursPerMonthTemp | Arbeitszähler appOpHoursPerMonth |
appOpHoursPerYear | Betriebsstunden des Jahres |
appOpHoursPerYearTemp | Arbeitszähler appOpHoursPerYear |
appUtilization | Auslastung = pulseTimePerDay /(vergangene Sekunden seit Tagesbeginn) * 100 |
appUtilizationTemp | Arbeitsvariable zu appUtilization |
Beginn der Woche ist jeweils der Sonntag.
Mit folgender Anweisung aktivieren wir die Erweiterungen:
define CN.Event notify CN.Test:(countsOverall:|value:|tickHour:|tickDay:|tickWeek:|tickMonth:|tickYear:).* {appHCNotify("%NAME","%EVTPART0","%EVTPART1");;}
Spätestens nach einer steigenden und einer fallenden Flanke sind die zuvor genannten app*-Readings zu sehen.
Die neuen Readings werden automatisch in den "Setter" der Web-Oberflächen aufgenommen. Dies gilt für alle Readings, die mit "app" beginnen.
Somit können die neuen Readings beliebig manipuliert werden.
Archiv für Tages-/Wochen-/Monats-/Jahreswerte anlegen
Nun wollen wir die aggregierten Werte in eine eigene Datei speichern. Dies gelingt mit
define CN.Test.FileDay FileLog ./log/CN.Test-Day-%Y.log CN.Test:app\w+ (Utilization|PerHour|PerDay|PerWeek|PerMonth|PerYear)(?!Temp).*
Im Klartext:
- verwende alle Werte des Counters CN.Test, deren Reading mit "app" beginnt
- und die einen der Terme appUtilization|PerHour|PerDay|PerWeek|PerMonth|PerYear beinhalten
- und die danach nicht dem Term "Temp" beinhalten
Fragen und Antworten
Betriebsstundenzähler über Leistungsmessung ableiten
Frage: Ich würde gerne zählen, wenn ich mehr Strom als Standy verbrauche (also mehr als 2Watt) und keine Betriebsstunden zählen, wenn der Verbrauch unter 2 Watt ist. Ist das möglich?
Beispiel für die Events
013-11-18_19:40:32 XXX power: 1.9 2013-11-18_19:40:32 XXX consumption: 2 2013-11-18_19:40:32 XXX consumptionTotal: 2 2013-11-18_19:40:36 XXX power: 27 2013-11-18_19:40:36 XXX consumption: 2 2013-11-18_19:40:36 XXX consumptionTotal: 2 2013-11-18_19:40:42 XXX power: 34.6 2013-11-18_19:40:42 XXX consumption: 2
Antwort
define CN.Test HourCounter XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$ XXX:power:\s[0-9]{1}(\.[0-9]{1,3})*$
Erläuterung zu <regexp_for_ON> = XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$
- "XXX" bezeichnet das Device, der Term danach ist der regexp-Filte für das On-Ereignis
- "power:" das Ereignis muss mit diesem Term beginnen
- "\s" es muss ein Leerzeichen folgen
- "[0-9]{2,}" es müssen mindestens 2 Ziffern folgen
- "(\.[0-9]{1,3})*" wenn ein Punkt folgt, dann müssen auf diesen mindestens 1..3 Ziffern folgen
- "$" danach darf kein weiteres Zeichen mehr folgen
Welche Anwendungsfälle sind denkbar ?
- Betriebsstundenzähler für meine "Fliegenkiller-Steckdose"
- Nutzungsdauer beschränken für TV,Internet oder Spielkonsolen für entnervte Eltern
- Nutzungsdauer ermitteln zur Energieeinsparung (Klimageräte, Ventilatoren, Dunstabzugshauben etc.)
- Lüftungsverhalten ermitteln (wie lange Fenster pro Tag geöffnet)