HourCounter: Unterschied zwischen den Versionen

Aus FHEMWiki
Zeile 200: Zeile 200:


==== Installation ====
==== Installation ====
99_UtilsHourCounter ist in das Verzeichnis der Module zu kopieren (beim [[Raspberry Pi]] /opt/fhem/FHEM).
99_UtilsHourCounter aus dem Verzeichnis "contrib" ist in das Verzeichnis der Module zu kopieren (beim [[Raspberry Pi]] /opt/fhem/FHEM).


==== Readings ====
==== Readings ====

Version vom 23. Oktober 2014, 18:27 Uhr

HourCounter
Zweck / Funktion
HourCounter dient zum Zählen von Ereignissen und zur Erfassung von Betriebsstunden
Allgemein
Typ Inoffiziell
Details
Dokumentation siehe Forum
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 
und 0=letztes Ereignis war OFF-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

HourCounter

Anwendung

Nachfolgende Darstellung zeigt das Einschaltverhalten eines Heizungskessels zusammen mit den abgeleiteten Werten.

13 11 15 HourCounter Chart.png

  • 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: 13 11 16 HourCounter ChartBuild 01.png

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.

Info green.pngDie 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.

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 Stromverbrauch

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