FHEM Tutorial-Reihe - Part 28: Energiemessung + Notification wenn Spülmaschine fertig

Mit ** gekennzeichnete Links auf dieser Seite sind Affiliatelinks.

FHEM Tutorial-Reihe - Part 28: Energiemessung + Notification wenn Spülmaschine fertig
FHEM Tutorial-Reihe - Part 28: Energiemessung + Notification wenn Spülmaschine fertig
  • Matthias Kleine
  • 03.03.2017
  • Hardware
  • Z-Wave
  • Integration
  • Energie

Wieviel Strom verbrauchen eigentlich Eure Geräte so? Also nicht die kleinen, die selten Mal an sind, sondern wirkliche Energiefresser wie z.B. der Kühlschrank oder ein Warmwasserspeicher. Diese Frage habe ich mir auch gestellt und mir daher für mein Z-Wave-System ein paar von den Fibaro-Zwischensteckern bestellt, welche man sowohl drahtlos schalten kann, als auch die aktuellen Leistungsdaten übermittelt bekommt. Zusätzlich lasse ich mich jetzt per Push-Notification informieren, wenn die Spülmaschine fertig ist und ich diese ausräumen kann.

Achtung: Dieser Inhalt wurde vor mehreren Jahren aufgenommen und ist nicht mehr aktuell! Es ist nicht empfohlen nach dieser Anleitung vorzugehen.

Was wird benötigt?

  • Eine FHEM-Installation
  • Ein Zwischenstecker, welcher die aktuelle Leistung misst
  • Das entsprechende Interface für FHEM

Video

Hausbau-Kurs

Komponenten

Z-Wave USB Stick (ZMEEUZB1) **

FIBARO Wall Plug / Z-Wave Plus Smart Steckdose Plug mit Leistungsmessung Typ F, FGWPF-102 **

Homematic Funk-Schaltaktor 1-fach mit Leistungsmessung, Zwischenstecker Typ F, 130248A0B **

Befehle

Generell werden alle Geräte hier beim Pairing automatisch angelegt. Daher brauchen wir nur das notify entsprechend konfigurieren. Da mache ich es eigentlich immer so, dass ich erst das notify mit einem leeren “Aktionsblock” anlege, und später in FHEM dann über den viel besseren Editor dann programmiere.

define n_KU_Spuelmaschine_start notify KU_Spuelmaschine:power:.* {}

Dann bearbeite ich das define und fügen folgenden Inhalt ein:

KU_Spuelmaschine:power:.* {
     if (ReadingsNum("KU_Spuelmaschine", "power", 0) > 10 && ReadingsVal("KU_Spuelmaschine", "running", "off") eq "off") {
          fhem("setreading KU_Spuelmaschine running on");
     }

     if (ReadingsNum("KU_Spuelmaschine", "power", 0) < 1 && ReadingsVal("KU_Spuelmaschine", "running", "off") eq "on") {
          fhem("setreading KU_Spuelmaschine running off");
          fhem("set WEB_Pushover msg 'Spülmaschine' 'Die Spülmaschine ist fertig'");
     }
}

Wie im Video erklärt erledige ich mit einem notify direkt mehrere Aufgaben. Das ist sinnvoll um den Code möglichst kurz zu halten und Dinge die zusammen gehören übersichtlich an einer Stelle zu finden. Möchte ich die Notification also irgendwann einmal nicht mehr haben, lösche ich einfach das komplette notify und muss nicht an zig andere Dummy-Devices denken.

Erklärung

Generell funktioniert das Ganze wie folgt:

  1. Die Spülmaschine wird eingeschaltet und das power-Reading ändert sich, wodurch das notify reagiert
  2. Sollte die Spülmaschine in diesem Moment mehr als 10 Watt verbrauchen, gehen wir davon aus dass sie eingeschaltet wurde und setzen auf der Spülmaschine das Reading “running” auf “on”. Falls der Wert kleiner als 10 Watt ist, passiert gar nichts, da das Reading “running” ja noch nicht auf “on” steht.
  3. Jetzt kommen noch zig hundert power-Änderungen, welche den aktuellen Verbrauch dokumentieren. Da aber alle Werte für “power” größer als 1 Watt sind und das Reading “running” ja bereits auf “on” steht, passiert nichts.
  4. Wenn die Spülmaschine fertig ist, schaltet sich diese ab. Dadurch ändert sich das Reading “power” natürlich wieder (z.B. auf 0) und nun greift der zweite Teil des notify, denn 0 ist kleiner als 1 und das Reading “running” steht ja noch auf “on”.
  5. Wir setzen also in diesem Fall das Reading “running” wieder auf “off” (um die erste if-Bedingung wieder scharf zu machen) und senden eine Push-Notification, dass die Spülmaschine jetzt fertig ist.

Eigentlich gar nicht so schwer, oder? Und das alles, ohne auch nur an Watchdog, Dummy oder was auch immer zu denken. Keep it simple!

Zusätzliches

Falls der Editor nicht so schön aussehen sollte wie bei mir, setzt das Attribut “JavaScripts” auf dem WEB-Device einmal wie folgt:

attr WEB JavaScripts codemirror/fhem_codemirror.js

Update

Hausbau-Kurs
{ReadingsTimestamp("KU_Spuelmaschine", "running", 0)} // Gibt mir die aktuelle Zeit von einem Reading zurück
{time_str2num(ReadingsTimestamp("KU_Spuelmaschine", "running", 0))} // Formatiert die Reading-Zeit in einen Unix-Timestamp
{ReadingsAge("KU_Spuelmaschine", "running", 0)} // Alter des Readings in Sekunden

{gettimeofday()} // 1529514418.37716 (aus Time::HiRes, gibt die Sekunden und Mikrosekunden seit 01.01.1970 00:00 zurück)
{time()} // 1529514712 (gibt die Sekunden seit 01.01.1970 00:00 zurück => Unix Timestamp)
{localtime()} // Wed Jun 20 19:08:33 2018 (gibt ein Array zurück => $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
{gmtime()} // Wed Jun 20 17:10:32 2018 (genau wie localtime, nur GMT und nicht aktuelle Zeitzone)
{TimeNow()} // 2018-06-20 19:05:57 entspricht {FmtDateTime(gettimeofday())}

{time_str2num(TimeNow())} // Wandelt ein FHEM-Datum in einen Unix-Timestamp um (in diesen Fall den aktuellen Zeitpunkt) => Ist also genau das gleiche wie {time()}

{time() - time_str2num(ReadingsTimestamp("KU_Spuelmaschine", "running", 0))} // Ist das gleiche wie ReadingsAge()

Datums- und Zeit-Funktionen

Nochmal etwas übersichtlicher als Tabelle. Welchen Arten gibt es, das aktuelle Datum und die Uhrzeit zu holen?

  Aufruf Rückgabe Erklärung
Aktueller Unix-Timestamp time() 1529514712 Sekunden seit 01.01.1970 00:00
Aktueller Unix-Timestamp gettimeofday() 1529514418.37716 Mikrosekunden seit 01.01.1970 00:00
Aktuelles Datum und Uhrzeit localtime() Wed Jun 20 19:08:33 2018 Array mit allen Zeitinformationen
Aktuelles Datum und Uhrzeit (GMT) gmtime() Wed Jun 20 17:10:32 2018 Array mit allen Zeitinformationen
Aktuelles Datum und Uhrzeit (FHEM) TimeNow() 2018-06-20 19:05:57 String im FHEM-Format

Hilfs-Funktionen (Umrechnung)

  Funktion Rückgabe Beispiel
FHEM-Datum zu Unix-Timestamp time_str2num($v) 1529514712 time_str2num(TimeNow()) == time()
Unix-Timestamp zu FHEM-Datum FmtDateTime($v) 2018-06-20 19:05:57 FmtDateTime(gettimeofday()) == TimeNow()
Zeitstempel eines Readings ReadingsTimestamp($g, $r, $d) 2018-06-20 19:05:57 ReadingsTimestamp('KU_Spuelmaschine', 'running', 0)
Alter eines Readings (in Sekunden) ReadingsAge($g, $r, $d) 154 ReadingsAge('KU_Spuelmaschine', 'running', 0)

Beispiele

Aufgabe Code
Unix-Timestamp eines Readings time_str2num(ReadingsTimestamp('KU_Spuelmaschine', 'running', 0))
Alter eines Readings in Sekunden entspricht ReadingsAge time() - time_str2num(ReadingsTimestamp('KU_Spuelmaschine', 'running', 0))
Aktuelle Uhrzeit im FHEM-Format strftime('%H:%M:%S', localtime())

Perl-Beispiele aus dem Video

Für die myUtils - eine Funktion um mit Zeitdifferenzen leichter zu Arbeiten. Die Funktion gibt entweder die Zeit in Sekunden seit der Änderung des angegebenen Readings zurück, oder -1 falls das Reading nicht gefunden wurde. Theoretisch könnte auch 0 zurückgegeben werden, wenn diese Funktion in der gleichen Sekunde nach der Änderung eines Readings aufgerufen wird.

Anstatt dieser Funktion kann auch ReadingsAge() aus dem Core genutzt werden.

sub secondsSinceReadingChange($$) {
	my ($device, $reading) = @_;
	my $readingsTimestamp = ReadingsTimestamp($device, $reading, "failed");

	if ($readingsTimestamp ne "failed") {
		return time() - time_str2num($readingsTimestamp);
	} else {
		return -1;
	}
}
KU_Spuelmaschine:power:.* {
	# Wenn die Spülmaschine eingeschaltet wurde
	if (ReadingsNum($NAME, "power", 0) > 10 && ReadingsVal($NAME, "running", "off") eq "off") {
		fhem("setreading $NAME running on");
	}

	# Wenn die Spülmaschine länger als 5 Minuten lief und dann keinen Strom mehr verbraucht -> Notification
	if (ReadingsNum($NAME, "power", 0) < 1 && ReadingsVal($NAME, "running", "off") eq "on") {
		if (secondsSinceReadingChange($NAME, "running") > 300) {
			fhem("set WEB_Pushover msg 'Spülmaschine' 'Die Spülmaschine ist fertig'");
			fhem("set lametric msg 'i1167' 'Spülmaschine fertig' 'notifications:water1' '1'");
			fhem("set Wunderlist addTask Spülmaschine ausräumen");
		}

		fhem("setreading $NAME running off");
	}

	# Wenn Fehler aufgetreten ist, und die Spülmaschine nach 4 Stunden nicht automatisch ausgegangen ist
	if (secondsSinceReadingChange($NAME, "running") > 14400 && ReadingsVal($NAME, "running", "off") eq "on") {
		fhem("setreading $NAME running off");

		fhem("set WEB_Pushover msg 'Spülmaschine' 'Die Spülmaschine läuft seit 4 Stunden und ist nicht ausgegangen'");
	}
}
Du willst mehr?

Smart-Home-Trainings von A-Z

Steig noch tiefer in die Themen ein und meistere Deine Projekte! Über 13.000 Teilnehmer konnten sich schon von der Qualität der Online-Kurse überzeugen.

ioBroker-Master-Kurs

ioBroker-Master-Kurs

Mehr Infos
Hausbau-Kurs

Hausbau mit KNX

Mehr Infos
Lox-Kurs

Lox-Kurs

Mehr Infos
Node-RED-Master-Kurs

Node-RED-Master-Kurs

Mehr Infos