HourCounter: Unterschied zwischen den Versionen
John (Diskussion | Beiträge) |
K (Sortierung bei Spalte Beschreibung entfernt; sonstige kleinere Korrekturen) |
||
Zeile 1: | Zeile 1: | ||
'''HourCounter''' ist ein Perl-Modul, das die Anzahl von Ereignissen erfasst. | '''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. | ||
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 == | == Features == | ||
Zeile 11: | Zeile 9: | ||
== Zielsetzung des WIKI-Artikels == | == Zielsetzung des WIKI-Artikels == | ||
Erläuterung der Funktionalität zur weiterführenden Diskussion im | Erläuterung der Funktionalität zur weiterführenden Diskussion im [http://forum.fhem.de/index.php/topic,12216.msg104162.html#msg104162 Forum]. | ||
[http://forum.fhem.de/index.php/topic,12216.msg104162.html#msg104162 Forum] | |||
== Status == | == Status == | ||
Das Modul befindet sich noch in der Evaluierungs-Phase. | Das Modul befindet sich noch in der Evaluierungs-Phase. | ||
[http://forum.fhem.de/index.php/topic,12216.msg133594.html#msg133594 Version 1.00 ] | [http://forum.fhem.de/index.php/topic,12216.msg133594.html#msg133594 Version 1.00 ] | ||
[http://forum.fhem.de/index.php/topic,12216.msg150639.html#msg150639 Version 1.02] | [http://forum.fhem.de/index.php/topic,12216.msg150639.html#msg150639 Version 1.02] | ||
== Voraussetzungen == | == Voraussetzungen == | ||
Keine. | |||
Das Modul ist, anders als das Vorgängerskript 99_UtilsMaxCounter, nicht mehr auf Max-Komponenten beschränkt. | |||
== Definition == | == Definition == | ||
===Abstrakt=== | === Abstrakt === | ||
<pre>define <name> HourCounter <regexp_for_ON> [<regexp_for_Off>]</pre> | <pre>define <name> HourCounter <regexp_for_ON> [<regexp_for_Off>]</pre> | ||
<regexp_for_ON> ist ein regulärer Ausdruck der das Ereignis beschreibt. | <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 | Wenn auch [<regexp_for_Off>] definiert ist, so sprechen wir von einem bipolarem Ereignis, das einen | ||
EIN- sowie einen AUS-Zustand aufweist. | EIN- sowie einen AUS-Zustand aufweist. | ||
<regexp_for_ON> | |||
Die Struktur des regexp-Ausdruckes ist analog zu jener beim Notify aufgebaut. | <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=== | ===Konkret=== | ||
Zeile 46: | Zeile 46: | ||
</pre> | </pre> | ||
Soll ein Dummy als Ereignis-Geber verwendet werden, lautet die Definition wie folgt: | |||
<pre> define CN.Test HourCounter myDummy:1 myDummy:0</pre> | <pre> define CN.Test HourCounter myDummy:1 myDummy:0</pre> | ||
Die neue Instanz weist folgende Struktur auf | Die neue Instanz weist folgende Struktur auf: | ||
<pre> | <pre> | ||
Zeile 92: | Zeile 92: | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
! Reading !! Beschreibung | ! Reading !! class="unsortable" | Beschreibung | ||
|- | |- | ||
| clearDate || Datum, zu dem alle kumulativen Readings über set .. clear gelöscht wurden | | clearDate || Datum, zu dem alle kumulativen Readings über set .. clear gelöscht wurden | ||
Zeile 146: | Zeile 146: | ||
[[Datei:13_11_15_HourCounter_Chart.png]] | [[Datei:13_11_15_HourCounter_Chart.png]] | ||
* die Kurve "Brenner EIN" zeigt die Trigger-Signale | * 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 "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 "Betriebsstunden" zeigt die aufgelaufene Zeit aus dem Reading pulseTimePerDay umgerechnet zu Stunden | ||
Zeile 153: | Zeile 153: | ||
=== Chart der Aktualwerte === | === Chart der Aktualwerte === | ||
Wir benötigen hierzu ein File-Archiv für die aufgelaufenen Daten. | Wir benötigen hierzu ein File-Archiv für die aufgelaufenen Daten. | ||
<pre>define CN.Test.File FileLog ./log/CN.Test-%Y.log (CN\.Test:.*)</pre> | <pre>define CN.Test.File FileLog ./log/CN.Test-%Y.log (CN\.Test:.*)</pre> | ||
Zeile 193: | Zeile 192: | ||
* Zuordnung von Verbräuchen zu unterschiedlichen Countern nach bestimmten Bedingungen | * 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 | Vor allem die Aggregation erfasster Werte in Stunden-, Tages-, Wochen- und Monatswerten ist eine sinnvolle | ||
Erweiterung bei der Verbrauchserfassung. | Erweiterung bei der Verbrauchserfassung. | ||
HourCounter bietet Schnittstellen an, die es ermöglichen das Modul selbst mit neuen Eigenschaften zu erweitern. | 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. | Die Referenz-Implementierung in 99_UtilsHourCounter.pm zeigt, wie dies skript-technisch zu realisieren ist. | ||
==== Installation ==== | ==== Installation ==== | ||
99_UtilsHourCounter ist in das Verzeichnis der Module zu kopieren ( | 99_UtilsHourCounter ist in das Verzeichnis der Module zu kopieren (beim [[Raspberry Pi]] /opt/fhem/FHEM). | ||
==== Readings ==== | ==== Readings ==== | ||
Zeile 207: | Zeile 206: | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
! Reading !! Beschreibung | ! Reading !! class="unsortable" | Beschreibung | ||
|- | |- | ||
| appCountsPerHour || Stundenzähler, wird bei Stundenwechsel aktualisiert | | appCountsPerHour || Stundenzähler, wird bei Stundenwechsel aktualisiert | ||
Zeile 249: | Zeile 248: | ||
Beginn der Woche ist jeweils der Sonntag.<br /> | Beginn der Woche ist jeweils der Sonntag.<br /> | ||
Mit folgender Anweisung aktivieren wir die Erweiterungen: | Mit folgender Anweisung aktivieren wir die Erweiterungen: | ||
< | :<code>define CN.Event notify CN.Test:(countsOverall:|value:|tickHour:|tickDay:|tickWeek:|tickMonth:|tickYear:).* {appHCNotify("%NAME","%EVTPART0","%EVTPART1");;}</code> | ||
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. | Spätestens nach einer steigenden und einer fallenden Flanke sind die zuvor genannten app*-Readings zu sehen. | ||
{{Randnotiz|RNTyp=Info|Die gezeigten define-Anweisungen müssen jeweils in einer Zeile stehen (keine Zeilenumbrüche!).}} | |||
Die neuen Readings werden automatisch in den "Setter" der Web-Oberflächen aufgenommen. | |||
Dies gilt für alle Readings, die mit "app" beginnen. | 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. | Somit können die neuen Readings beliebig manipuliert werden. | ||
==== Archiv für Tages-/Wochen-/Monats-/Jahreswerte anlegen ==== | ==== Archiv für Tages-/Wochen-/Monats-/Jahreswerte anlegen ==== | ||
Nun wollen wir die aggregierten Werte in eine eigene Datei speichern. | Nun wollen wir die aggregierten Werte in eine eigene Datei speichern. Dies gelingt mit | ||
Dies gelingt mit | :<code>define CN.Test.FileDay FileLog ./log/CN.Test-Day-%Y.log CN.Test:app\w+ (Utilization|PerHour|PerDay|PerWeek|PerMonth|PerYear)(?!Temp).* </code> | ||
< | |||
define CN.Test.FileDay FileLog ./log/CN.Test-Day-%Y.log CN.Test:app\w+ | |||
(Utilization|PerHour|PerDay|PerWeek|PerMonth|PerYear)(?!Temp).* | |||
</ | |||
Im Klartext: | Im Klartext: | ||
Zeile 279: | Zeile 270: | ||
== Fragen und Antworten == | == Fragen und Antworten == | ||
ToDo | ToDo | ||
[[Kategorie:MAX]] | [[Kategorie:MAX]] | ||
[[Kategorie:HOWTOS]] | [[Kategorie:HOWTOS]] |
Version vom 20. März 2014, 12:23 Uhr
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 Wochen- Tages- u. 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.
Status
Das Modul befindet sich noch in der Evaluierungs-Phase.
Voraussetzungen
Keine.
Das Modul ist, anders als das Vorgängerskript 99_UtilsMaxCounter, nicht mehr auf Max-Komponenten beschränkt.
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 Jahres 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 wurde 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 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
ToDo