<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Albatros</id>
	<title>FHEMWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Albatros"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Albatros"/>
	<updated>2026-04-13T06:36:49Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HourCounter&amp;diff=9413</id>
		<title>HourCounter</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HourCounter&amp;diff=9413"/>
		<updated>2015-01-18T09:55:35Z</updated>

		<summary type="html">&lt;p&gt;Albatros: /* Betriebsstundenzähler über Leistungsmessung ableiten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=HourCounter dient zum Zählen von Ereignissen und zur Erfassung von Betriebs-/Ruhe-Zeiten&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCmdRef=LightScene -- nicht erforderlich, da Modultyp x --&amp;gt;&lt;br /&gt;
|ModForumArea=MAX&lt;br /&gt;
|ModTechName=98_HourCounter.pm&lt;br /&gt;
|ModOwner=John ([http://forum.fhem.de/index.php?action=profile;u=806 Forum] / [[Benutzer Diskussion:John|Wiki]])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[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.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Ermittlung von Betriebsstunden, Auslastung, Verbräuchen, Schalthäufigkeiten&lt;br /&gt;
* Ermittlung der Häufigkeit, Puls- Pausendauer pro Tag&lt;br /&gt;
* Ermittlung der Puls-/Pausendauer der letzten Schaltperiode&lt;br /&gt;
* Bereitstellung von Ereignissen zur Fortführung der Kumulation für Tages-, Wochen- und Monatswerte&lt;br /&gt;
* unterstützende Funktionen zur Ablage von Tages-, Wochen- und Monatswerten&lt;br /&gt;
&lt;br /&gt;
== Zielsetzung des WIKI-Artikels ==&lt;br /&gt;
Erläuterung der Funktionalität zur weiterführenden Diskussion im [http://forum.fhem.de/index.php/topic,12216.msg72596.html#msg72596 Forum].&lt;br /&gt;
&lt;br /&gt;
== Aktuelle Version ==&lt;br /&gt;
Das Modul ist seit dem 24.10.2014 Bestandteil von FHEM.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
=== Abstrakt ===&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; HourCounter &amp;lt;regexp_for_ON&amp;gt; [&amp;lt;regexp_for_Off&amp;gt;]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;regexp_for_ON&amp;gt; ist ein regulärer Ausdruck der das Ereignis beschreibt.&lt;br /&gt;
&lt;br /&gt;
Wenn auch [&amp;lt;regexp_for_Off&amp;gt;] definiert ist, so sprechen wir von einem bipolarem Ereignis, das einen &lt;br /&gt;
EIN- sowie einen AUS-Zustand aufweist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;regexp_for_ON&amp;gt; beschreibt in diesem Fall die positive Flanke,[&amp;lt;regexp_for_Off&amp;gt;] die negative Flanke. Die Struktur des regexp-Ausdruckes ist analog zu jener beim Notify aufgebaut.&lt;br /&gt;
&lt;br /&gt;
===Konkret===&lt;br /&gt;
&amp;lt;pre&amp;gt;define CN.Test HourCounter SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
Hier wird der HourCounter CN.TEST definiert.&lt;br /&gt;
Ein MAX-Fensterkontakt mit Namen SHUTTER.JOHN wird als Ereignis-Geber verwendet.&lt;br /&gt;
Das Reading &amp;quot;onoff&amp;quot; wird als Trigger für unserem Zähler genutzt.&lt;br /&gt;
Bei den Fensterkontakten sehen diese Ereignisse wie folgt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-11-15 23:19:12 MAX SHUTTER.JOHN onoff: 1&lt;br /&gt;
....&lt;br /&gt;
2013-11-15 23:19:24 MAX SHUTTER.JOHN onoff: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soll ein Dummy als Ereignis-Geber verwendet werden, lautet die Definition wie folgt:&lt;br /&gt;
&amp;lt;pre&amp;gt; define CN.Test HourCounter myDummy:1 myDummy:0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die neue Instanz weist folgende Struktur auf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internals:&lt;br /&gt;
   CFGFN      &lt;br /&gt;
   DEF        SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0&lt;br /&gt;
   NAME       CN.Test&lt;br /&gt;
   NR         738&lt;br /&gt;
   NTFY_ORDER 50-CN.Test&lt;br /&gt;
   STATE      1&lt;br /&gt;
   TYPE       HourCounter&lt;br /&gt;
   Readings:&lt;br /&gt;
     2014-02-04 20:59:22   clearDate       2014-02-04 20:59:22&lt;br /&gt;
     2014-02-04 20:59:57   countsOverall   1&lt;br /&gt;
     2014-02-04 20:59:57   countsPerDay    1&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimeIncrement 35&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimeOverall 35&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimePerDay 35&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimeIncrement 4&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimeOverall 4&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimePerDay 4&lt;br /&gt;
     2014-02-04 20:59:57   state           1&lt;br /&gt;
     2014-02-04 21:00:00   tickHour        1&lt;br /&gt;
     2014-02-04 21:00:01   value           0&lt;br /&gt;
   Helper:&lt;br /&gt;
     OFF_Regexp SHUTTER.JOHN:onoff:.0&lt;br /&gt;
     ON_Regexp  SHUTTER.JOHN:onoff:.1&lt;br /&gt;
     calledByEvent &lt;br /&gt;
     changedTimestamp 2014-02-04 21:00:01&lt;br /&gt;
     forceClear &lt;br /&gt;
     forceDayChange &lt;br /&gt;
     forceHourChange &lt;br /&gt;
     forceMonthChange &lt;br /&gt;
     forceWeekChange &lt;br /&gt;
     isFirstRun &lt;br /&gt;
     sdRoundHourLast 1391544000&lt;br /&gt;
     value      0&lt;br /&gt;
     cmdQueue:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit nicht zu viele Ereignisse in den Log-Dateien landen, kann man diese sinnvoll einschränken, so daß&lt;br /&gt;
nur Änderungen das Feuern von Events auslösen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr CN.BRENNER event-on-change-reading .*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn sich nun jedoch über Stunden und Tage nichts ändert, sieht man in den Charts keine Daten mehr.&lt;br /&gt;
Mit dieser Anweisung wird erreicht, daß alle Readings nach Aktualisierung spätesten nach 1 Stunden einen Event feuern, auch wenn sich der Wert nicht ändert.&lt;br /&gt;
Eine Ausnahme hiervon sollen machen die  tick*-Readings, deren Events sollen immer sofort gefeuert werden, &lt;br /&gt;
wenn sie aktualisiert werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr CN.BRENNER event-min-interval tick.*:0,.*:3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reading !! class=&amp;quot;unsortable&amp;quot; |  Beschreibung &lt;br /&gt;
|-&lt;br /&gt;
| clearDate || Datum, zu dem alle kumulativen Readings  über set .. clear gelöscht wurden&lt;br /&gt;
|-&lt;br /&gt;
| countsOverall || Absolutzähler für das Auftreten des ON-Ereignisses&lt;br /&gt;
|-&lt;br /&gt;
| countsPerDay  || Tageszähler für das Auftreten des ON-Ereignisses&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeIncrement || Zeitdauer der Pausen-Phase in Sekunden ; wird zyklisch aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeEdge || Zeitdauer der letzten komplettierten Pausen-Phase&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeOverall || Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimePerDay || Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen des akt. Tages&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeIncrement ||  Zeitdauer der Puls-Phase in Sekunden ; wird zyklisch aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeEdge || Zeitdauer der letzten komplettierten Pulse-Phase&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeOverall || Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimePerDay || Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen des akt. Tages&lt;br /&gt;
|-&lt;br /&gt;
| value || Aktueller Schaltzustand gemäss ON/OFF Ereignis,&amp;lt;br /&amp;gt;&lt;br /&gt;
 mit 1=letztes Ereignis war ON-Ereignis &amp;lt;br /&amp;gt;&lt;br /&gt;
 und 0=letztes Ereignis war OFF-Ereignis&lt;br /&gt;
|-&lt;br /&gt;
| tickUpdated || Event wird gefeuert, wenn die operativen Readings beschrieben worden sind (nicht unbedingt gändert)&lt;br /&gt;
|-&lt;br /&gt;
| tickChanged || Event wird nach Änderung von value gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickDay || Event wird nach Tageswechsel gefeuert bevor die Tageszähler resettiert werden&lt;br /&gt;
|-&lt;br /&gt;
| tickHour || Event wird nach Stundenwechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickWeek || Event wird nach Wochenwechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickMonth || Event wird nach Monatswechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickYear || Event wird nach Jahreswechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| forceHourChange || simuliert einen Stundenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceDayChange || simuliert einen Tageswechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceWeekChange || simuliert einen Wochenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceMonthChange || simuliert einen Monatswechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceYearChange || simuliert einen Jahreswechsel&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Web-Oberfläche ==&lt;br /&gt;
[[Datei:13_11_15_HourCounter_Face.png|HourCounter]]&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Nachfolgende Darstellung zeigt das Einschaltverhalten eines Heizungskessels zusammen mit den &lt;br /&gt;
abgeleiteten Werten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:13_11_15_HourCounter_Chart.png]]&lt;br /&gt;
&lt;br /&gt;
* die Kurve &amp;quot;Brenner EIN&amp;quot; zeigt die Trigger-Signale des ON/OFF Filters, also das Ein-/Ausschalten des Brenners&lt;br /&gt;
* die Kurve &amp;quot;Brenner-Starts&amp;quot; zeigt die über den Tag aufgelaufenen Starts, also chronologisch das Anwachsen von Reading countsPerDay&lt;br /&gt;
* die Kurve &amp;quot;Betriebsstunden&amp;quot; zeigt die aufgelaufene Zeit aus dem Reading pulseTimePerDay umgerechnet zu Stunden&lt;br /&gt;
* die Kurve &amp;quot;Dauer&amp;quot; zeigt die Dauer des letzten Pulses in Sekunden&lt;br /&gt;
* die Kurve Auslastung zeigt das Verhältnis des Readings pulseTimePerDay zur seit Tagesbeginn vergangenen Zeit.&lt;br /&gt;
&lt;br /&gt;
=== Chart der Aktualwerte ===&lt;br /&gt;
Wir benötigen hierzu ein File-Archiv für die aufgelaufenen Daten.&lt;br /&gt;
&amp;lt;pre&amp;gt;define CN.Test.File FileLog ./log/CN.Test-%Y.log (CN\.Test:.*)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Man erhält nach den ersten Ereignissen Einträge in folgender Form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-11-16_12:45:40 CN.Test value: 1&lt;br /&gt;
2013-11-16_12:45:40 CN.Test 1&lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimeIncrement: 41    &lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimePerDay: 41&lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimeOverall: 41&lt;br /&gt;
2013-11-16_12:46:21 CN.Test value: 0&lt;br /&gt;
2013-11-16_12:50:38 CN.Test countsPerDay: 2&lt;br /&gt;
2013-11-16_12:50:38 CN.Test countsOverall: 2&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimeIncrement: 257&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimePerDay: 756&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimeOverall: 756&lt;br /&gt;
2013-11-16_12:50:38 CN.Test value: 1&lt;br /&gt;
2013-11-16_12:50:38 CN.Test 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann man den Chart definieren:&lt;br /&gt;
[[Datei:13_11_16_HourCounter_ChartBuild_01.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Kurve &amp;quot;Brenner EIN&amp;quot; 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:&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]=~&amp;quot;1&amp;quot;?-2:-19&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die &amp;quot;Brenner Starts&amp;quot; können wir direkt von countsPerDay ableiten.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Für die &amp;quot;Betriebsstunden&amp;quot; verwenden wir pulseTimePerDay. Da diese in Sekunden vorliegen teilen wir den Wert durch 3600, um Stunden zu erhalten.&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]/=3600&amp;lt;/pre&amp;gt;&lt;br /&gt;
Als letzten versorgen wir noch die Kurve &amp;quot;Dauer&amp;quot; mit pulseTimeIncrement. Da wir diese in Minuten haben wollen ist ebenfalls eine Umformung nötig.&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]/=60&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Somit sind die Basis-Kurven angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Erweiterungen ===&lt;br /&gt;
Es wurden im Forum viele Wünsche formuliert, weitere Funktionalitäten für den HourCounter einzuführen.&lt;br /&gt;
&lt;br /&gt;
* Aggregation über bestimmte oder ganz freie Zeiträume&lt;br /&gt;
* komplexe Berechnungen, die zum Verbrauch führen&lt;br /&gt;
* Zuordnung von Verbräuchen zu unterschiedlichen Countern nach bestimmten Bedingungen&lt;br /&gt;
&lt;br /&gt;
Vor allem die Aggregation erfasster Werte in Stunden-, Tages-, Wochen- und Monatswerten ist eine sinnvolle&lt;br /&gt;
Erweiterung bei der Verbrauchserfassung.&lt;br /&gt;
&lt;br /&gt;
HourCounter bietet Schnittstellen an, die es ermöglichen, das Modul selbst mit neuen Eigenschaften zu erweitern.&lt;br /&gt;
&lt;br /&gt;
Die Referenz-Implementierung in 99_UtilsHourCounter.pm zeigt, wie dies skript-technisch zu realisieren ist.&lt;br /&gt;
&lt;br /&gt;
==== Installation ====&lt;br /&gt;
Die jeweils aktuelle Version von 99_UtilsHourCounter kann über diesen &lt;br /&gt;
[http://sourceforge.net/p/fhem/code/HEAD/tree/trunk/fhem/contrib/99_UtilsHourCounter.pm?format=raw Link] bezogen werden.&lt;br /&gt;
&lt;br /&gt;
==== Readings ====&lt;br /&gt;
99_UtilsHourCounter erweitert den HourCounter um folgende Funktionen:&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reading !! class=&amp;quot;unsortable&amp;quot; |  Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerHour || Stundenzähler, wird bei Stundenwechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerHourTemp || Arbeitszähler zu appCountsPerHour&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerDay || Tageszähler, wird bei Tageswechsel aktualisiert (Arbeitszähler ist countsPerDay)&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerWeek || Wochenzähler, wird bei Wochenwechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerWeekTemp || Arbeitszähler zu appCountsPerWeek&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerMonth || Monatszähler, wird bei Monatswechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerMonthTemp || Arbeitszähler zu appCountsPerMonth&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerYear || Jahreszähler, wird bei Jahreswechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerYearTemp || Arbeitszähler zu appCountsPerYear&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerDay || Betriebsstunden des Tages&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerDayTemp || Arbeitszähler zu appOpHoursPerDay&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerWeek || Betriebsstunden der Woche&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerWeekTemp || Arbeitszähler zu appOpHoursPerWeek&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerMonth || Betriebsstunden des Monats&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerMonthTemp || Arbeitszähler appOpHoursPerMonth&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerYear || Betriebsstunden des Jahres&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerYearTemp || Arbeitszähler appOpHoursPerYear&lt;br /&gt;
|-&lt;br /&gt;
| appUtilization || Auslastung = pulseTimePerDay /(vergangene Sekunden seit Tagesbeginn) * 100&lt;br /&gt;
|-&lt;br /&gt;
| appUtilizationTemp || Arbeitsvariable zu appUtilization&lt;br /&gt;
|}&lt;br /&gt;
Beginn der Woche ist jeweils der Sonntag.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit folgender Anweisung aktivieren wir die Erweiterungen: &lt;br /&gt;
:&amp;lt;code&amp;gt;&lt;br /&gt;
define CN.EVENT notify CN\..*:tick.* { appHCNotify(&amp;quot;%NAME&amp;quot;,&amp;quot;%EVTPART0&amp;quot;,&amp;quot;%EVTPART1&amp;quot;);;}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Spätestens nach einer steigenden und einer fallenden Flanke sind die zuvor genannten app*-Readings zu sehen.&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Die gezeigten define-Anweisungen müssen jeweils in einer Zeile stehen (keine Zeilenumbrüche!).}}&lt;br /&gt;
&lt;br /&gt;
Die neuen Readings werden automatisch  in den &amp;quot;Setter&amp;quot; der Web-Oberflächen aufgenommen. Dies gilt für alle Readings, die mit &amp;quot;app&amp;quot; beginnen.&lt;br /&gt;
&lt;br /&gt;
Somit können die neuen Readings beliebig manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
==== Archiv für Tages-/Wochen-/Monats-/Jahreswerte anlegen ====&lt;br /&gt;
Nun wollen wir die aggregierten Werte in eine eigene Datei speichern. Dies gelingt mit &lt;br /&gt;
:&amp;lt;code&amp;gt;define CN.Test.FileDay FileLog ./log/CN.Test-Day-%Y.log CN.Test:app\w+ (Utilization|PerHour|PerDay|PerWeek|PerMonth|PerYear)(?!Temp).* &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Klartext:&lt;br /&gt;
* verwende alle Werte des Counters CN.Test, deren Reading mit &amp;quot;app&amp;quot; beginnt&lt;br /&gt;
* und die einen der Terme appUtilization|PerHour|PerDay|PerWeek|PerMonth|PerYear beinhalten&lt;br /&gt;
* und die danach nicht dem Term &amp;quot;Temp&amp;quot; beinhalten&lt;br /&gt;
&lt;br /&gt;
== Fragen und Antworten ==&lt;br /&gt;
==== Betriebsstundenzähler über Leistungsmessung ableiten ====&lt;br /&gt;
&#039;&#039;&#039;Frage:&#039;&#039;&#039;&lt;br /&gt;
Ich würde gerne zählen, wenn ich mehr Strom als Standy verbrauche (also mehr als 2Watt)&lt;br /&gt;
und keine Betriebsstunden zählen, wenn der Verbrauch unter 2 Watt ist. Ist das möglich?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Beispiel für die Events&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
013-11-18_19:40:32 XXX power: 1.9&lt;br /&gt;
2013-11-18_19:40:32 XXX consumption: 2&lt;br /&gt;
2013-11-18_19:40:32 XXX consumptionTotal: 2&lt;br /&gt;
2013-11-18_19:40:36 XXX power: 27&lt;br /&gt;
2013-11-18_19:40:36 XXX consumption: 2&lt;br /&gt;
2013-11-18_19:40:36 XXX consumptionTotal: 2&lt;br /&gt;
2013-11-18_19:40:42 XXX power: 34.6&lt;br /&gt;
2013-11-18_19:40:42 XXX consumption: 2 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
Die hier vorgestellte Lösung überprüft ob der Wert des Events power eine oder zwei Ziffern vor dem Komma hat.&lt;br /&gt;
Deshalb wir hier erst gezählt, wenn die Schwelle von 10Watt überschritten wird. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define CN.Test HourCounter XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$  XXX:power:\s[0-9]{1}(\.[0-9]{1,3})*$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erläuterung zu &amp;lt;regexp_for_ON&amp;gt; = XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$&lt;br /&gt;
* &amp;quot;XXX&amp;quot;  bezeichnet das Device, der Term danach ist der regexp-Filte für das On-Ereignis&lt;br /&gt;
* &amp;quot;power:&amp;quot; das Ereignis muss mit diesem Term beginnen&lt;br /&gt;
* &amp;quot;\s&amp;quot; es muss ein Leerzeichen folgen&lt;br /&gt;
* &amp;quot;[0-9]{2,}&amp;quot; es müssen mindestens 2 Ziffern folgen&lt;br /&gt;
* &amp;quot;(\.[0-9]{1,3})*&amp;quot; wenn ein Punkt folgt, dann müssen auf diesen mindestens 1..3 Ziffern folgen&lt;br /&gt;
* &amp;quot;$&amp;quot; danach darf kein weiteres Zeichen mehr folgen&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort Möglichkeit 2&#039;&#039;&#039;&lt;br /&gt;
In dieser Lösung bekommt das entsprechende Device was mit HourCounter überwacht werden soll ein userReadings &amp;quot;onoff&amp;quot;. Dieses Reading wird dann zum Schalten von Hour Counter verwendet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define GPIO4_DS18B20_Waermepumpe_Vorlauf GPIO4 28-000005956079&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf alias Wärmepumpe Vorlauf&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf model DS18B20&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf room GPIO4&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf userReadings onoff {(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)?1:0;;}&lt;br /&gt;
&lt;br /&gt;
define Waermepumpe_HourCounter HourCounter GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.1  GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.0&lt;br /&gt;
attr Waermepumpe_HourCounter room 2_Fussbodenheizung&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erläuterungen zu dem Code: &amp;quot;{(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)?1:0;;}&amp;quot;&lt;br /&gt;
* &amp;quot;(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)&amp;quot; Diese Bedingung für das userReadings onoff prüft bei jedem Event, ob der Wert von temperature größer als 28 ist. &lt;br /&gt;
* &amp;quot;?1:0&amp;quot; Ist dies der Fall wird das userReading onoff auf 1 gesetzt andernfalls auf 0.&lt;br /&gt;
Auf Basis deses UserReadings wird dann der HourCounter definiert:&lt;br /&gt;
* &amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.1&amp;quot; Einschaltbedingung für HourCounter&lt;br /&gt;
* &amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.0&amp;quot; Abschaltbedingung für Hour Counter&lt;br /&gt;
&lt;br /&gt;
==== Welche Anwendungsfälle sind denkbar ? ====&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg175163.html#msg175163 Aus dem Forum]&lt;br /&gt;
* Betriebsstundenzähler für meine &amp;quot;Fliegenkiller-Steckdose&amp;quot;&lt;br /&gt;
* Nutzungsdauer beschränken für TV,Internet oder Spielkonsolen für entnervte Eltern&lt;br /&gt;
* Nutzungsdauer ermitteln zur Energieeinsparung (Klimageräte, Ventilatoren, Dunstabzugshauben etc.)&lt;br /&gt;
* Lüftungsverhalten ermitteln (wie lange Fenster pro Tag geöffnet)&lt;br /&gt;
&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg195358.html#msg195358 Brenner Starts/Verbrauch + akkumulierte Werte]&lt;br /&gt;
&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg196358.html#msg196358 Ölverbrauch+Solar-Ladung]&lt;br /&gt;
&lt;br /&gt;
[http://voizchat.de/gaszaehler-verbrauch-erfassen-mit-fhem-und-raspberry-gpio/ Gaszähler mit HourCounter realisieren]&lt;br /&gt;
==== Seltene Schaltvorgänge ====&lt;br /&gt;
Die Schaltvorgänge sind über den Tag sehr wenige. Die Aktualisierung erfolgt immer erst&lt;br /&gt;
bei der negativen Flanke. Wie kann man eine häufigere Aktualisierung erreichen ?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ab Version 1.0.0.6 ist wurde das Attribut &amp;quot;interval&amp;quot; eingeführt; es ist auf 60 Minuten voreingestellt und kann von 5..60 im 5 Minuten-Raster festgelegt werden.&lt;br /&gt;
Es bestimmt, nach welcher Zeit Puls-/Pausendauer aktualisiert werden sollen, unabhängig vom Auftreten einer Schaltflanke.&lt;br /&gt;
&lt;br /&gt;
==== Korrekte Darstellung der akkumulierten Daten im Chart ====&lt;br /&gt;
&#039;&#039;&#039;Frage&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;appCountsPerDay: 4&amp;quot; bezieht sich auf die Counts des Tages 2014-06-16, trägt aber selbst den Zeitstempel 2014-06-17 und wird demnach in einem Chart auch über den Tag  &amp;quot; 2014-06-17&amp;quot; dargestellt.&lt;br /&gt;
Das Problem betrifft alle akkumulierten Daten des HourCounters.&lt;br /&gt;
Wie erreicht man im Chart die korrekte Darstellung ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Thema wurde [http://forum.fhem.de/index.php/topic,12216.msg239929.html#msg239929 hier] disktuiert.&lt;br /&gt;
Eine Lösung findet man mit [http://www.fhemwiki.de/wiki/LogProxy LogProxy].&lt;br /&gt;
Damit läßt sich ein negativer Offset für die X-Achse definieren, so daß die Daten wieder korrekt dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:MAX]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Albatros</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HourCounter&amp;diff=9412</id>
		<title>HourCounter</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HourCounter&amp;diff=9412"/>
		<updated>2015-01-18T09:55:14Z</updated>

		<summary type="html">&lt;p&gt;Albatros: /* Betriebsstundenzähler über Leistungsmessung ableiten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=HourCounter dient zum Zählen von Ereignissen und zur Erfassung von Betriebs-/Ruhe-Zeiten&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCmdRef=LightScene -- nicht erforderlich, da Modultyp x --&amp;gt;&lt;br /&gt;
|ModForumArea=MAX&lt;br /&gt;
|ModTechName=98_HourCounter.pm&lt;br /&gt;
|ModOwner=John ([http://forum.fhem.de/index.php?action=profile;u=806 Forum] / [[Benutzer Diskussion:John|Wiki]])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[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.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Ermittlung von Betriebsstunden, Auslastung, Verbräuchen, Schalthäufigkeiten&lt;br /&gt;
* Ermittlung der Häufigkeit, Puls- Pausendauer pro Tag&lt;br /&gt;
* Ermittlung der Puls-/Pausendauer der letzten Schaltperiode&lt;br /&gt;
* Bereitstellung von Ereignissen zur Fortführung der Kumulation für Tages-, Wochen- und Monatswerte&lt;br /&gt;
* unterstützende Funktionen zur Ablage von Tages-, Wochen- und Monatswerten&lt;br /&gt;
&lt;br /&gt;
== Zielsetzung des WIKI-Artikels ==&lt;br /&gt;
Erläuterung der Funktionalität zur weiterführenden Diskussion im [http://forum.fhem.de/index.php/topic,12216.msg72596.html#msg72596 Forum].&lt;br /&gt;
&lt;br /&gt;
== Aktuelle Version ==&lt;br /&gt;
Das Modul ist seit dem 24.10.2014 Bestandteil von FHEM.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
=== Abstrakt ===&lt;br /&gt;
&amp;lt;pre&amp;gt;define &amp;lt;name&amp;gt; HourCounter &amp;lt;regexp_for_ON&amp;gt; [&amp;lt;regexp_for_Off&amp;gt;]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;regexp_for_ON&amp;gt; ist ein regulärer Ausdruck der das Ereignis beschreibt.&lt;br /&gt;
&lt;br /&gt;
Wenn auch [&amp;lt;regexp_for_Off&amp;gt;] definiert ist, so sprechen wir von einem bipolarem Ereignis, das einen &lt;br /&gt;
EIN- sowie einen AUS-Zustand aufweist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;regexp_for_ON&amp;gt; beschreibt in diesem Fall die positive Flanke,[&amp;lt;regexp_for_Off&amp;gt;] die negative Flanke. Die Struktur des regexp-Ausdruckes ist analog zu jener beim Notify aufgebaut.&lt;br /&gt;
&lt;br /&gt;
===Konkret===&lt;br /&gt;
&amp;lt;pre&amp;gt;define CN.Test HourCounter SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
Hier wird der HourCounter CN.TEST definiert.&lt;br /&gt;
Ein MAX-Fensterkontakt mit Namen SHUTTER.JOHN wird als Ereignis-Geber verwendet.&lt;br /&gt;
Das Reading &amp;quot;onoff&amp;quot; wird als Trigger für unserem Zähler genutzt.&lt;br /&gt;
Bei den Fensterkontakten sehen diese Ereignisse wie folgt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-11-15 23:19:12 MAX SHUTTER.JOHN onoff: 1&lt;br /&gt;
....&lt;br /&gt;
2013-11-15 23:19:24 MAX SHUTTER.JOHN onoff: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soll ein Dummy als Ereignis-Geber verwendet werden, lautet die Definition wie folgt:&lt;br /&gt;
&amp;lt;pre&amp;gt; define CN.Test HourCounter myDummy:1 myDummy:0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die neue Instanz weist folgende Struktur auf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Internals:&lt;br /&gt;
   CFGFN      &lt;br /&gt;
   DEF        SHUTTER.JOHN:onoff:.1 SHUTTER.JOHN:onoff:.0&lt;br /&gt;
   NAME       CN.Test&lt;br /&gt;
   NR         738&lt;br /&gt;
   NTFY_ORDER 50-CN.Test&lt;br /&gt;
   STATE      1&lt;br /&gt;
   TYPE       HourCounter&lt;br /&gt;
   Readings:&lt;br /&gt;
     2014-02-04 20:59:22   clearDate       2014-02-04 20:59:22&lt;br /&gt;
     2014-02-04 20:59:57   countsOverall   1&lt;br /&gt;
     2014-02-04 20:59:57   countsPerDay    1&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimeIncrement 35&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimeOverall 35&lt;br /&gt;
     2014-02-04 20:59:57   pauseTimePerDay 35&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimeIncrement 4&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimeOverall 4&lt;br /&gt;
     2014-02-04 21:00:01   pulseTimePerDay 4&lt;br /&gt;
     2014-02-04 20:59:57   state           1&lt;br /&gt;
     2014-02-04 21:00:00   tickHour        1&lt;br /&gt;
     2014-02-04 21:00:01   value           0&lt;br /&gt;
   Helper:&lt;br /&gt;
     OFF_Regexp SHUTTER.JOHN:onoff:.0&lt;br /&gt;
     ON_Regexp  SHUTTER.JOHN:onoff:.1&lt;br /&gt;
     calledByEvent &lt;br /&gt;
     changedTimestamp 2014-02-04 21:00:01&lt;br /&gt;
     forceClear &lt;br /&gt;
     forceDayChange &lt;br /&gt;
     forceHourChange &lt;br /&gt;
     forceMonthChange &lt;br /&gt;
     forceWeekChange &lt;br /&gt;
     isFirstRun &lt;br /&gt;
     sdRoundHourLast 1391544000&lt;br /&gt;
     value      0&lt;br /&gt;
     cmdQueue:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit nicht zu viele Ereignisse in den Log-Dateien landen, kann man diese sinnvoll einschränken, so daß&lt;br /&gt;
nur Änderungen das Feuern von Events auslösen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr CN.BRENNER event-on-change-reading .*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Wenn sich nun jedoch über Stunden und Tage nichts ändert, sieht man in den Charts keine Daten mehr.&lt;br /&gt;
Mit dieser Anweisung wird erreicht, daß alle Readings nach Aktualisierung spätesten nach 1 Stunden einen Event feuern, auch wenn sich der Wert nicht ändert.&lt;br /&gt;
Eine Ausnahme hiervon sollen machen die  tick*-Readings, deren Events sollen immer sofort gefeuert werden, &lt;br /&gt;
wenn sie aktualisiert werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr CN.BRENNER event-min-interval tick.*:0,.*:3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reading !! class=&amp;quot;unsortable&amp;quot; |  Beschreibung &lt;br /&gt;
|-&lt;br /&gt;
| clearDate || Datum, zu dem alle kumulativen Readings  über set .. clear gelöscht wurden&lt;br /&gt;
|-&lt;br /&gt;
| countsOverall || Absolutzähler für das Auftreten des ON-Ereignisses&lt;br /&gt;
|-&lt;br /&gt;
| countsPerDay  || Tageszähler für das Auftreten des ON-Ereignisses&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeIncrement || Zeitdauer der Pausen-Phase in Sekunden ; wird zyklisch aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeEdge || Zeitdauer der letzten komplettierten Pausen-Phase&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimeOverall || Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen&lt;br /&gt;
|-&lt;br /&gt;
| pauseTimePerDay || Zeitdauer in Sekunden über alle aufgetretenen Pause-Phasen des akt. Tages&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeIncrement ||  Zeitdauer der Puls-Phase in Sekunden ; wird zyklisch aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeEdge || Zeitdauer der letzten komplettierten Pulse-Phase&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimeOverall || Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen&lt;br /&gt;
|-&lt;br /&gt;
| pulseTimePerDay || Zeitdauer in Sekunden über alle aufgetretenen Puls-Phasen des akt. Tages&lt;br /&gt;
|-&lt;br /&gt;
| value || Aktueller Schaltzustand gemäss ON/OFF Ereignis,&amp;lt;br /&amp;gt;&lt;br /&gt;
 mit 1=letztes Ereignis war ON-Ereignis &amp;lt;br /&amp;gt;&lt;br /&gt;
 und 0=letztes Ereignis war OFF-Ereignis&lt;br /&gt;
|-&lt;br /&gt;
| tickUpdated || Event wird gefeuert, wenn die operativen Readings beschrieben worden sind (nicht unbedingt gändert)&lt;br /&gt;
|-&lt;br /&gt;
| tickChanged || Event wird nach Änderung von value gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickDay || Event wird nach Tageswechsel gefeuert bevor die Tageszähler resettiert werden&lt;br /&gt;
|-&lt;br /&gt;
| tickHour || Event wird nach Stundenwechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickWeek || Event wird nach Wochenwechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickMonth || Event wird nach Monatswechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| tickYear || Event wird nach Jahreswechsel gefeuert&lt;br /&gt;
|-&lt;br /&gt;
| forceHourChange || simuliert einen Stundenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceDayChange || simuliert einen Tageswechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceWeekChange || simuliert einen Wochenwechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceMonthChange || simuliert einen Monatswechsel&lt;br /&gt;
|-&lt;br /&gt;
| forceYearChange || simuliert einen Jahreswechsel&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Web-Oberfläche ==&lt;br /&gt;
[[Datei:13_11_15_HourCounter_Face.png|HourCounter]]&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Nachfolgende Darstellung zeigt das Einschaltverhalten eines Heizungskessels zusammen mit den &lt;br /&gt;
abgeleiteten Werten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:13_11_15_HourCounter_Chart.png]]&lt;br /&gt;
&lt;br /&gt;
* die Kurve &amp;quot;Brenner EIN&amp;quot; zeigt die Trigger-Signale des ON/OFF Filters, also das Ein-/Ausschalten des Brenners&lt;br /&gt;
* die Kurve &amp;quot;Brenner-Starts&amp;quot; zeigt die über den Tag aufgelaufenen Starts, also chronologisch das Anwachsen von Reading countsPerDay&lt;br /&gt;
* die Kurve &amp;quot;Betriebsstunden&amp;quot; zeigt die aufgelaufene Zeit aus dem Reading pulseTimePerDay umgerechnet zu Stunden&lt;br /&gt;
* die Kurve &amp;quot;Dauer&amp;quot; zeigt die Dauer des letzten Pulses in Sekunden&lt;br /&gt;
* die Kurve Auslastung zeigt das Verhältnis des Readings pulseTimePerDay zur seit Tagesbeginn vergangenen Zeit.&lt;br /&gt;
&lt;br /&gt;
=== Chart der Aktualwerte ===&lt;br /&gt;
Wir benötigen hierzu ein File-Archiv für die aufgelaufenen Daten.&lt;br /&gt;
&amp;lt;pre&amp;gt;define CN.Test.File FileLog ./log/CN.Test-%Y.log (CN\.Test:.*)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Man erhält nach den ersten Ereignissen Einträge in folgender Form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2013-11-16_12:45:40 CN.Test value: 1&lt;br /&gt;
2013-11-16_12:45:40 CN.Test 1&lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimeIncrement: 41    &lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimePerDay: 41&lt;br /&gt;
2013-11-16_12:46:21 CN.Test pulseTimeOverall: 41&lt;br /&gt;
2013-11-16_12:46:21 CN.Test value: 0&lt;br /&gt;
2013-11-16_12:50:38 CN.Test countsPerDay: 2&lt;br /&gt;
2013-11-16_12:50:38 CN.Test countsOverall: 2&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimeIncrement: 257&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimePerDay: 756&lt;br /&gt;
2013-11-16_12:50:38 CN.Test pauseTimeOverall: 756&lt;br /&gt;
2013-11-16_12:50:38 CN.Test value: 1&lt;br /&gt;
2013-11-16_12:50:38 CN.Test 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann man den Chart definieren:&lt;br /&gt;
[[Datei:13_11_16_HourCounter_ChartBuild_01.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Kurve &amp;quot;Brenner EIN&amp;quot; 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:&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]=~&amp;quot;1&amp;quot;?-2:-19&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die &amp;quot;Brenner Starts&amp;quot; können wir direkt von countsPerDay ableiten.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Für die &amp;quot;Betriebsstunden&amp;quot; verwenden wir pulseTimePerDay. Da diese in Sekunden vorliegen teilen wir den Wert durch 3600, um Stunden zu erhalten.&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]/=3600&amp;lt;/pre&amp;gt;&lt;br /&gt;
Als letzten versorgen wir noch die Kurve &amp;quot;Dauer&amp;quot; mit pulseTimeIncrement. Da wir diese in Minuten haben wollen ist ebenfalls eine Umformung nötig.&lt;br /&gt;
&amp;lt;pre&amp;gt;$fld[3]/=60&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Somit sind die Basis-Kurven angelegt.&lt;br /&gt;
&lt;br /&gt;
=== Erweiterungen ===&lt;br /&gt;
Es wurden im Forum viele Wünsche formuliert, weitere Funktionalitäten für den HourCounter einzuführen.&lt;br /&gt;
&lt;br /&gt;
* Aggregation über bestimmte oder ganz freie Zeiträume&lt;br /&gt;
* komplexe Berechnungen, die zum Verbrauch führen&lt;br /&gt;
* Zuordnung von Verbräuchen zu unterschiedlichen Countern nach bestimmten Bedingungen&lt;br /&gt;
&lt;br /&gt;
Vor allem die Aggregation erfasster Werte in Stunden-, Tages-, Wochen- und Monatswerten ist eine sinnvolle&lt;br /&gt;
Erweiterung bei der Verbrauchserfassung.&lt;br /&gt;
&lt;br /&gt;
HourCounter bietet Schnittstellen an, die es ermöglichen, das Modul selbst mit neuen Eigenschaften zu erweitern.&lt;br /&gt;
&lt;br /&gt;
Die Referenz-Implementierung in 99_UtilsHourCounter.pm zeigt, wie dies skript-technisch zu realisieren ist.&lt;br /&gt;
&lt;br /&gt;
==== Installation ====&lt;br /&gt;
Die jeweils aktuelle Version von 99_UtilsHourCounter kann über diesen &lt;br /&gt;
[http://sourceforge.net/p/fhem/code/HEAD/tree/trunk/fhem/contrib/99_UtilsHourCounter.pm?format=raw Link] bezogen werden.&lt;br /&gt;
&lt;br /&gt;
==== Readings ====&lt;br /&gt;
99_UtilsHourCounter erweitert den HourCounter um folgende Funktionen:&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reading !! class=&amp;quot;unsortable&amp;quot; |  Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerHour || Stundenzähler, wird bei Stundenwechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerHourTemp || Arbeitszähler zu appCountsPerHour&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerDay || Tageszähler, wird bei Tageswechsel aktualisiert (Arbeitszähler ist countsPerDay)&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerWeek || Wochenzähler, wird bei Wochenwechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerWeekTemp || Arbeitszähler zu appCountsPerWeek&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerMonth || Monatszähler, wird bei Monatswechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerMonthTemp || Arbeitszähler zu appCountsPerMonth&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerYear || Jahreszähler, wird bei Jahreswechsel aktualisiert&lt;br /&gt;
|-&lt;br /&gt;
| appCountsPerYearTemp || Arbeitszähler zu appCountsPerYear&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerDay || Betriebsstunden des Tages&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerDayTemp || Arbeitszähler zu appOpHoursPerDay&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerWeek || Betriebsstunden der Woche&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerWeekTemp || Arbeitszähler zu appOpHoursPerWeek&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerMonth || Betriebsstunden des Monats&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerMonthTemp || Arbeitszähler appOpHoursPerMonth&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerYear || Betriebsstunden des Jahres&lt;br /&gt;
|-&lt;br /&gt;
| appOpHoursPerYearTemp || Arbeitszähler appOpHoursPerYear&lt;br /&gt;
|-&lt;br /&gt;
| appUtilization || Auslastung = pulseTimePerDay /(vergangene Sekunden seit Tagesbeginn) * 100&lt;br /&gt;
|-&lt;br /&gt;
| appUtilizationTemp || Arbeitsvariable zu appUtilization&lt;br /&gt;
|}&lt;br /&gt;
Beginn der Woche ist jeweils der Sonntag.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit folgender Anweisung aktivieren wir die Erweiterungen: &lt;br /&gt;
:&amp;lt;code&amp;gt;&lt;br /&gt;
define CN.EVENT notify CN\..*:tick.* { appHCNotify(&amp;quot;%NAME&amp;quot;,&amp;quot;%EVTPART0&amp;quot;,&amp;quot;%EVTPART1&amp;quot;);;}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Spätestens nach einer steigenden und einer fallenden Flanke sind die zuvor genannten app*-Readings zu sehen.&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Die gezeigten define-Anweisungen müssen jeweils in einer Zeile stehen (keine Zeilenumbrüche!).}}&lt;br /&gt;
&lt;br /&gt;
Die neuen Readings werden automatisch  in den &amp;quot;Setter&amp;quot; der Web-Oberflächen aufgenommen. Dies gilt für alle Readings, die mit &amp;quot;app&amp;quot; beginnen.&lt;br /&gt;
&lt;br /&gt;
Somit können die neuen Readings beliebig manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
==== Archiv für Tages-/Wochen-/Monats-/Jahreswerte anlegen ====&lt;br /&gt;
Nun wollen wir die aggregierten Werte in eine eigene Datei speichern. Dies gelingt mit &lt;br /&gt;
:&amp;lt;code&amp;gt;define CN.Test.FileDay FileLog ./log/CN.Test-Day-%Y.log CN.Test:app\w+ (Utilization|PerHour|PerDay|PerWeek|PerMonth|PerYear)(?!Temp).* &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Klartext:&lt;br /&gt;
* verwende alle Werte des Counters CN.Test, deren Reading mit &amp;quot;app&amp;quot; beginnt&lt;br /&gt;
* und die einen der Terme appUtilization|PerHour|PerDay|PerWeek|PerMonth|PerYear beinhalten&lt;br /&gt;
* und die danach nicht dem Term &amp;quot;Temp&amp;quot; beinhalten&lt;br /&gt;
&lt;br /&gt;
== Fragen und Antworten ==&lt;br /&gt;
==== Betriebsstundenzähler über Leistungsmessung ableiten ====&lt;br /&gt;
&#039;&#039;&#039;Frage:&#039;&#039;&#039;&lt;br /&gt;
Ich würde gerne zählen, wenn ich mehr Strom als Standy verbrauche (also mehr als 2Watt)&lt;br /&gt;
und keine Betriebsstunden zählen, wenn der Verbrauch unter 2 Watt ist. Ist das möglich?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Beispiel für die Events&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
013-11-18_19:40:32 XXX power: 1.9&lt;br /&gt;
2013-11-18_19:40:32 XXX consumption: 2&lt;br /&gt;
2013-11-18_19:40:32 XXX consumptionTotal: 2&lt;br /&gt;
2013-11-18_19:40:36 XXX power: 27&lt;br /&gt;
2013-11-18_19:40:36 XXX consumption: 2&lt;br /&gt;
2013-11-18_19:40:36 XXX consumptionTotal: 2&lt;br /&gt;
2013-11-18_19:40:42 XXX power: 34.6&lt;br /&gt;
2013-11-18_19:40:42 XXX consumption: 2 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
Die hier vorgestellte Lösung überprüft ob der Wert des Events power eine oder zwei Ziffern vor dem Komma hat.&lt;br /&gt;
Deshalb wir hier erst gezählt, wenn die Schwelle von 10Watt überschritten wird. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define CN.Test HourCounter XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$  XXX:power:\s[0-9]{1}(\.[0-9]{1,3})*$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erläuterung zu &amp;lt;regexp_for_ON&amp;gt; = XXX:power:\s[0-9]{2,}(\.[0-9]{1,3})*$&lt;br /&gt;
* &amp;quot;XXX&amp;quot;  bezeichnet das Device, der Term danach ist der regexp-Filte für das On-Ereignis&lt;br /&gt;
* &amp;quot;power:&amp;quot; das Ereignis muss mit diesem Term beginnen&lt;br /&gt;
* &amp;quot;\s&amp;quot; es muss ein Leerzeichen folgen&lt;br /&gt;
* &amp;quot;[0-9]{2,}&amp;quot; es müssen mindestens 2 Ziffern folgen&lt;br /&gt;
* &amp;quot;(\.[0-9]{1,3})*&amp;quot; wenn ein Punkt folgt, dann müssen auf diesen mindestens 1..3 Ziffern folgen&lt;br /&gt;
* &amp;quot;$&amp;quot; danach darf kein weiteres Zeichen mehr folgen&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antowrt Möglichkeit 2&#039;&#039;&#039;&lt;br /&gt;
In dieser Lösung bekommt das entsprechende Device was mit HourCounter überwacht werden soll ein userReadings &amp;quot;onoff&amp;quot;. Dieses Reading wird dann zum Schalten von Hour Counter verwendet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define GPIO4_DS18B20_Waermepumpe_Vorlauf GPIO4 28-000005956079&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf alias Wärmepumpe Vorlauf&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf model DS18B20&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf room GPIO4&lt;br /&gt;
attr GPIO4_DS18B20_Waermepumpe_Vorlauf userReadings onoff {(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)?1:0;;}&lt;br /&gt;
&lt;br /&gt;
define Waermepumpe_HourCounter HourCounter GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.1  GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.0&lt;br /&gt;
attr Waermepumpe_HourCounter room 2_Fussbodenheizung&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erläuterungen zu dem Code: &amp;quot;{(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)?1:0;;}&amp;quot;&lt;br /&gt;
* &amp;quot;(ReadingsVal(&amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf&amp;quot;,&amp;quot;temperature&amp;quot;,0) &amp;gt;28)&amp;quot; Diese Bedingung für das userReadings onoff prüft bei jedem Event, ob der Wert von temperature größer als 28 ist. &lt;br /&gt;
* &amp;quot;?1:0&amp;quot; Ist dies der Fall wird das userReading onoff auf 1 gesetzt andernfalls auf 0.&lt;br /&gt;
Auf Basis deses UserReadings wird dann der HourCounter definiert:&lt;br /&gt;
* &amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.1&amp;quot; Einschaltbedingung für HourCounter&lt;br /&gt;
* &amp;quot;GPIO4_DS18B20_Waermepumpe_Vorlauf:onoff:.0&amp;quot; Abschaltbedingung für Hour Counter&lt;br /&gt;
&lt;br /&gt;
==== Welche Anwendungsfälle sind denkbar ? ====&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg175163.html#msg175163 Aus dem Forum]&lt;br /&gt;
* Betriebsstundenzähler für meine &amp;quot;Fliegenkiller-Steckdose&amp;quot;&lt;br /&gt;
* Nutzungsdauer beschränken für TV,Internet oder Spielkonsolen für entnervte Eltern&lt;br /&gt;
* Nutzungsdauer ermitteln zur Energieeinsparung (Klimageräte, Ventilatoren, Dunstabzugshauben etc.)&lt;br /&gt;
* Lüftungsverhalten ermitteln (wie lange Fenster pro Tag geöffnet)&lt;br /&gt;
&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg195358.html#msg195358 Brenner Starts/Verbrauch + akkumulierte Werte]&lt;br /&gt;
&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,12216.msg196358.html#msg196358 Ölverbrauch+Solar-Ladung]&lt;br /&gt;
&lt;br /&gt;
[http://voizchat.de/gaszaehler-verbrauch-erfassen-mit-fhem-und-raspberry-gpio/ Gaszähler mit HourCounter realisieren]&lt;br /&gt;
==== Seltene Schaltvorgänge ====&lt;br /&gt;
Die Schaltvorgänge sind über den Tag sehr wenige. Die Aktualisierung erfolgt immer erst&lt;br /&gt;
bei der negativen Flanke. Wie kann man eine häufigere Aktualisierung erreichen ?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ab Version 1.0.0.6 ist wurde das Attribut &amp;quot;interval&amp;quot; eingeführt; es ist auf 60 Minuten voreingestellt und kann von 5..60 im 5 Minuten-Raster festgelegt werden.&lt;br /&gt;
Es bestimmt, nach welcher Zeit Puls-/Pausendauer aktualisiert werden sollen, unabhängig vom Auftreten einer Schaltflanke.&lt;br /&gt;
&lt;br /&gt;
==== Korrekte Darstellung der akkumulierten Daten im Chart ====&lt;br /&gt;
&#039;&#039;&#039;Frage&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;appCountsPerDay: 4&amp;quot; bezieht sich auf die Counts des Tages 2014-06-16, trägt aber selbst den Zeitstempel 2014-06-17 und wird demnach in einem Chart auch über den Tag  &amp;quot; 2014-06-17&amp;quot; dargestellt.&lt;br /&gt;
Das Problem betrifft alle akkumulierten Daten des HourCounters.&lt;br /&gt;
Wie erreicht man im Chart die korrekte Darstellung ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Thema wurde [http://forum.fhem.de/index.php/topic,12216.msg239929.html#msg239929 hier] disktuiert.&lt;br /&gt;
Eine Lösung findet man mit [http://www.fhemwiki.de/wiki/LogProxy LogProxy].&lt;br /&gt;
Damit läßt sich ein negativer Offset für die X-Achse definieren, so daß die Daten wieder korrekt dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:MAX]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Albatros</name></author>
	</entry>
</feed>