Hallo,
ich möchte gerne einen DOIF verwenden um die holiday-Einstellungen der FHT-Zentrale an Homematic-Geräte zu übertragen. Hierzu habe ich in 99_MyUtils eine Funktion angelegt, welche auch soweit funktioniert - anstelle des Befehls an die HM-Geräte, gibt diese derzeit jedoch nur den Befehl per print aus.
Das DOIF ist so definiert:
([FHT8B:mode] eq "holiday" or [FHT8B:mode] eq "holiday_short") ({setHolidayHM("[FHT8B:holiday1]","[FHT8B:holiday2]","[FHT8B:mode]","Heizung_Bad_Clima","8")})
Die Readings (mit dem error) sind:
Device FHT8B 2016-10-30 00:02:18
cmd_event FHT8B 2016-10-30 00:00:23
cmd_nr 1 2016-10-30 00:00:23
e_FHT8B_mode holiday 2016-10-30 00:02:18
error {setHolidayHM("1","11","holiday","Heizung_Bad_Clima","8")}: 1 2016-10-30 00:00:23
state cmd_1 2016-10-30 00:00:23
Laut Logfile müsste es funktionieren:
Zitatset Heizung_Bad_Clima controlParty 8 30.10.2016 0:30 1.11.2016 23:30
2016.10.30 00:00:23 2: SET_HM_HOLIDAY_ON: {setHolidayHM("1","11","holiday","Heizung_Bad_Clima","8")}: 1
Woher stammt aber der error?
Zitat von: dad401 am 30 Oktober 2016, 00:09:05
Hallo,
ich möchte gerne einen DOIF verwenden um die holiday-Einstellungen der FHT-Zentrale an Homematic-Geräte zu übertragen. Hierzu habe ich in 99_MyUtils eine Funktion angelegt, welche auch soweit funktioniert - anstelle des Befehls an die HM-Geräte, gibt diese derzeit jedoch nur den Befehl per print aus.
Das DOIF ist so definiert:
([FHT8B:mode] eq "holiday" or [FHT8B:mode] eq "holiday_short") ({setHolidayHM("[FHT8B:holiday1]","[FHT8B:holiday2]","[FHT8B:mode]","Heizung_Bad_Clima","8")})
Die Readings (mit dem error) sind:
Device FHT8B 2016-10-30 00:02:18
cmd_event FHT8B 2016-10-30 00:00:23
cmd_nr 1 2016-10-30 00:00:23
e_FHT8B_mode holiday 2016-10-30 00:02:18
error {setHolidayHM("1","11","holiday","Heizung_Bad_Clima","8")}: 1 2016-10-30 00:00:23
state cmd_1 2016-10-30 00:00:23
Laut Logfile müsste es funktionieren:
Woher stammt aber der error?
Wenn die Routine einen Returnwert ungleich Null liefert, dann wird es als Fehler interpretiert. Also einfach am Ende der Routine 0 zurückgeben.
Gruß
Damian
Stimmt, wenn ich die Routine manuell im Kommandofenster eingebe, bekomme ich eine 1 - und die Printausgabe der Funktion dann erst im FHEM-Logfile.
Dann irritiert mich jedoch, warum die Routine eigentlich 1 zurückgibt - hier mal die Routine im Entwurf:
##########################################################
# switch all Homematic Devices to holiday
#
sub setHolidayHM($$$$$)
{
my ($set_day, $set_month, $fht_mode, $hm_device, $hm_temp) = @_;
$set_day *= 1;
$set_month *= 1;
$hm_temp *= 1;
if ( ReadingsVal($hm_device,"controlMode","auto") eq "party" ) {
my @today = localtime;
my $mday = $today[3];
my $month = $today[4] + 1;
my $year = $today[5] + 1900;
my $hour = $today[2];
my $min = $today[1];
my $set_year = $year;
if ( $fht_mode eq "holiday_short" ) {
# holiday1 = hour, holiday2 = day
$set_day = $set_month;
if ( $set_day < $mday ) {
$set_month = $month + 1;
if ( $set_month > 12 ) {
$set_month = 1;
$set_year = $year + 1;
}
} else {
$set_month = $month;
}
} else {
if ( $set_month < $month ) {
$set_year = $year + 1;
}
}
print ("\nset $hm_device controlParty $hm_temp $mday.$month.$year $hour:30 $set_day.$set_month.$set_year 23:30\n");
print ("\set $hm_device burstXmit\n");
}
}
Logik-Hinweis: das erste if muss eigentlich 'eq "auto"' heissen und ist derzeit nur auf "party" gesetzt zum Testen (da das HM-Device derzeit im Partymodus ist).
Ziel: Wenn ich den FHT auf "Urlaub" stelle, sollen alle anderen HM-Devices den Urlaub übernehmen (ggf. mit unterschiedlichen desired-temp, daher als Parameter). Die Endzeit ist nicht so wichtig (23:30) - da die HM-Devices auch dann wieder aus dem Urlaub geholt werden, wenn der FHT wieder auf "auto" geht.
Zitat von: dad401 am 30 Oktober 2016, 10:30:43
Stimmt, wenn ich die Routine manuell im Kommandofenster eingebe, bekomme ich eine 1 - und die Printausgabe der Funktion dann erst im FHEM-Logfile.
Dann irritiert mich jedoch, warum die Routine eigentlich 1 zurückgibt - hier mal die Routine im Entwurf:
##########################################################
# switch all Homematic Devices to holiday
#
sub setHolidayHM($$$$$)
{
my ($set_day, $set_month, $fht_mode, $hm_device, $hm_temp) = @_;
$set_day *= 1;
$set_month *= 1;
$hm_temp *= 1;
if ( ReadingsVal($hm_device,"controlMode","auto") eq "party" ) {
my @today = localtime;
my $mday = $today[3];
my $month = $today[4] + 1;
my $year = $today[5] + 1900;
my $hour = $today[2];
my $min = $today[1];
my $set_year = $year;
if ( $fht_mode eq "holiday_short" ) {
# holiday1 = hour, holiday2 = day
$set_day = $set_month;
if ( $set_day < $mday ) {
$set_month = $month + 1;
if ( $set_month > 12 ) {
$set_month = 1;
$set_year = $year + 1;
}
} else {
$set_month = $month;
}
} else {
if ( $set_month < $month ) {
$set_year = $year + 1;
}
}
print ("\nset $hm_device controlParty $hm_temp $mday.$month.$year $hour:30 $set_day.$set_month.$set_year 23:30\n");
print ("\set $hm_device burstXmit\n");
}
}
Logik-Hinweis: das erste if muss eigentlich 'eq "auto"' heissen und ist derzeit nur auf "party" gesetzt zum Testen (da das HM-Device derzeit im Partymodus ist).
Ziel: Wenn ich den FHT auf "Urlaub" stelle, sollen alle anderen HM-Devices den Urlaub übernehmen (ggf. mit unterschiedlichen desired-temp, daher als Parameter). Die Endzeit ist nicht so wichtig (23:30) - da die HM-Devices auch dann wieder aus dem Urlaub geholt werden, wenn der FHT wieder auf "auto" geht.
Wie soll sie was sinnvolles zurückliefern, wenn du keinen Return-Befehl absetzt. Einfach am Ende deiner Routine return 0; schreiben.
Wenn man nichts zurückgeben muss, braucht es doch normalerweise kein return, oder?
Siehe Beispiele hier (http://www.fhemwiki.de/wiki/99_myUtils_anlegen).
Aber auch bei einem
{ print "hallo" }
in der FHEM-Kommandozeile, wird eine 1 zurückgegeben. Die Routine macht es dann richtig - die 1 stammt vom letzten print.
{ print "Hallo";;return 0 } gibt dann nichts zurück.
Wobei in Perl ein einfaches print doch nicht "1" zurückliefern sollte - was macht da FHEM?
Fazit:
Einbauen ist kein Problem - nur habe ich den Sinn oder das Zusammenspiel mit FHEM noch nicht richtig verstanden.
Zitat von: dad401 am 30 Oktober 2016, 10:42:16
Wenn man nichts zurückgeben muss, braucht es doch normalerweise kein return, oder?
Siehe Beispiele hier (http://www.fhemwiki.de/wiki/99_myUtils_anlegen).
Aber auch bei einem
{ print "hallo" }
in der FHEM-Kommandozeile, wird eine 1 zurückgegeben. Die Routine macht es dann richtig - die 1 stammt vom letzten print.
{ print "Hallo";;return 0 } gibt dann nichts zurück.
Wobei in Perl ein einfaches print doch nicht "1" zurückliefern sollte - was macht da FHEM?
Fazit:
Einbauen ist kein Problem - nur habe ich den Sinn oder das Zusammenspiel mit FHEM noch nicht richtig verstanden.
Offenbar liefert eine Routine in Perl immer etwas, ob man will oder nicht:
hier z. B.
sub test
{
my $s=10;
}
den Wert 10.
Wenn du es nicht dem Zufall (besser gesagt dem letzten Befehl) überlassen willst, dann solltest du einen wohldefinierten Returnwert liefern und dafür gibt es den return-Befehl.
Habe es nun angepasst. Der error in den Readings ist nun weg.
Wenn die Routine beim manuellen Aufruf eine 1 an FHEM zurückliefert, sollte man bei Verwendung der Routine im DOIF darauf achten und 0 rückgeben.
Zitat von: dad401 am 30 Oktober 2016, 11:56:29
Habe es nun angepasst. Der error in den Readings ist nun weg.
Wenn die Routine beim manuellen Aufruf eine 1 an FHEM zurückliefert, sollte man bei Verwendung der Routine im DOIF darauf achten und 0 rückgeben.
Das Reading heißt zwar error, man kann es auch als Warnung oder Sonstiges ansehen. Es soll den User darauf hinweisen, dass bei der Ausführung nicht 0 oder Leerstring zurück geliefert wurde, was möglicherweise auf einen Fehler hinweist.
Damit kann der Anwender insb. bei eigenen Perl-Routinen steuern, ob alles ok ist oder eben nicht und hat dann neben dem Log eine weitere Information im DOIF-Modul.
Gruß
Damian
Da die Routine als letztes einen print macht - der auch in der FHEM-Befehlszeile { print "hallo" } eine 1 auswirft, nehme ich an, dass es in Ordnung ist.
Aber es stimmt schon, dass man komplexere Routinen programmieren und bei Fehlern einen Rückgabecode liefert, den man dann direkt im DOIF auch sieht, falls der Fehler auftritt.
Zitat von: dad401 am 30 Oktober 2016, 19:04:08
Da die Routine als letztes einen print macht - der auch in der FHEM-Befehlszeile { print "hallo" } eine 1 auswirft, nehme ich an, dass es in Ordnung ist.
Aber es stimmt schon, dass man komplexere Routinen programmieren und bei Fehlern einen Rückgabecode liefert, den man dann direkt im DOIF auch sieht, falls der Fehler auftritt.
Der Grund für die Existenz dieses Reading ist ganz einfach. Die Befehlsketten, ob FHEM-Befehle oder Perlbefehle in geschweiften Klammern, werden an eine Routine in fhem.pl übergeben. Ein FHEM-Befehl, der auf einen Fehler läuft, bringt diesen Fehler zurück im Klartext, damit ist der Returnwert nicht leer oder 0, sondern beinhaltet diesen Fehler im Klartext. Dieser wird protokolliert und zusätzlich im error-Reading festgehalten. Wenn alles gut geht, liefert der FHEM-Befehl nichts bzw. leeren String und dann wird error-Reading nicht belegt. Genauso werden auch Perlbefehle in geschweiften Klammern von dieser Routine behandelt. Beides wird vom DOIF gleich behandelt und führt zum beschriebenen Belegen des Readings error im "Fehlerfalle".
Gruß
Damian