Hallo,
ich versuche mich gerade an einer Funktion in der 99_myUtils.pm - ausgelöst über ein notify.
Folgendes habe ich vor:
Ich prüfe per LAN-Ping auf eine IP-Adresse, ob ein bestimmtes Smartphone "anwesend" ist (=PRESENCE)
define Sebi PRESENCE lan-ping 10.100.100.21
Ein notify soll nun eine Funktion aufrufen (99_myUtils.pm) um einige Prüfungen durchzuführen und dann einen Status im Typ ROOMMATE zu ändern.
define n.SetHomeStatusSebi notify Sebi:state:.* { SetHomeStatusSebi($EVENT) }
Nun die Funktion:
sub SetHomeStatusSebi($)
{
my $SetStatus = @_;
my $NewStatus = '';
my $CurrentStatus = ReadingsVal("rr_Sebi", "state", "");
if ( ( $CurrentStatus == "gotosleep") && ($SetStatus == "home") ){
my $NewStatus = "gotosleep";
}
if ( ( $CurrentStatus == "gone") && ($NewStatus == "home") ){
my $NewStatus = "home";
}
if ( ( $CurrentStatus == "absent") && ($NewStatus == "home") ){
my $NewStatus = "home";
}
if ( ( $CurrentStatus == "home") && ($NewStatus == "home") ){
my $NewStatus = "home";
}
if ( ( $CurrentStatus == "absent" ) && ($NewStatus == "absent") ){
my $absentTime = ReadingsVal("rr_Sebi", "durTimerAbsence_cr", "");
if ( ( $absentTime > 0 ) && ($absentTime <= 15 ) ) {
my $NewStatus = "absent";
}
if ( $absentTime > 15 ) {
my $NewStatus = "gone";
}
}
set rr_Sebi $NewStatus;
}
Was soll passieren? Nun, wenn das Handy anwesend ist, soll auch der Homestatus von rr_Sebi auf "home" gesetzt werden, aber nur dann, wenn der Status nicht "gotosleep" ist.
Wenn das Handy nicht anwesend ist wird der Homestatus auf "absent" gesetzt, ist der Satus bereits "absent" und das schon länger als 15 min, soll der Homestatus auf "gone" gesetzt werden.
Irgendwo habe ich einen Fehler, nur wo finde ich nicht. Vielleicht kann mir ja jemand einen Schups in die Richtige Richtung geben?
Danke für Eure Unterstützung.
Sollte das am Schluss nicht
fhem "set rr_Sebi $NewStatus";
heißen?
Das war auf jeden Fall einer der Fehler. Danke!
Ich habe die Vermutung dass meine Variablen nicht gefüllt sind. Kann ich denn durch eine Anweisung debuggen welcher Wert gerade in welcher Variable steckt?
so alá print($var) und im Log (oder irgendwo anders) sehe ich dann den aktuellen Wert?
Ich glaube hier liegt der Fehler:
my $SetStatus = @_;
my $CurrentStatus = ReadingsVal("rr_Sebi", "state", "");
Log 1,"SetStatus: ".$SetStatus." CurrentStatus: ".$CurrentStatus;
Gruß
Hans
Danke Hans! Das bringt mich weiter.
Mein Log sagt jetzt:
2016.01.22 12:26:22 1: SetStatus: presence: absent CurrentStatus: home
Sprich, die Variable SetStaus enthällt momentan "presence: absent"
Ich möchte aber nur "absent" in der Variable haben.
Wie bekomme ich den Wert aus:
my $SetStatus = @_;
ohne "presence: " ?
Versucht habe ich nun folgendes:
my ($SetStatusTmp1) = @_;
my @SetStatusTmp2 = split(/: /,$SetStatusTmp1);
my $SetStatus = @SetStatusTmp2[2];
jedoch ohne Erfolg, die Variable $SetStatus is nun leer.
commandref zu notify lesen und dich mit den Events beschäftigen. Teile eines Events erhält man über $EVTPARTX (siehe commandref).
Die Indexierung beginnt bei 0:
my $SetStatus = @SetStatusTmp2[1];
Eleganter und mehr fhem-like ist aber Marvins Vorschlag.
Gruß
Hans
Ich habe mir die ommandref zu notify nochmal genauer angesehen. Mit $EVTPART1 klappt jetzt alles wie gewünscht.
Das mit der Indexierung hätte mir auch gleich auffallen können - ist ja in den meisten Programmiersprachen gleich *schande über mich*. $EVTPART1 ist auf jeden Fall sinnvoller als der Split.
Hier der neue, funktionierende code aus der 99_myUtils.pm (falls es jemanden helfen sollte):
sub SetHomeStatusSebi($)
{
my ($SetStatus) = @_;
my $NewStatus = "";
my $CurrentStatus = Value("rr_Sebi");
my $absentTime = ReadingsVal("rr_Sebi", "durTimerAbsence_cr", 1);
if ( ( $CurrentStatus eq "gotosleep") && ($SetStatus eq "present") ){
$NewStatus = "gotosleep";
}
if ( ( $CurrentStatus eq "gone") && ($SetStatus eq "present") ){
$NewStatus = "home";
}
if ( ( $CurrentStatus eq "absent") && ($SetStatus eq "present") ){
$NewStatus = "home";
}
if ( ( $CurrentStatus eq "home") && ($SetStatus eq "present") ){
$NewStatus = "home";
}
if ( ( $CurrentStatus eq "home") && ($SetStatus eq "absent") ){
$NewStatus = "absent";
}
if ( ( $CurrentStatus eq "absent" ) && ($SetStatus eq "absent") ){
if ($absentTime < 15 ) {
$NewStatus = "absent";
}
if ( $absentTime >= 15 ) {
$NewStatus = "gone";
}
}
if($NewStatus ne $CurrentStatus){
fhem "set rr_Sebi $NewStatus";
Log 1,"SEBI: SetStatus: ".$SetStatus." CurrentStatus: ".$CurrentStatus." NewStatus: ".$NewStatus." AbsentTime: ".$absentTime;
}
}
Ich möchte damit verschiedene Dinge steuern:
- Benachrichtung per WhatsApp falls keiner zuhause ist und Fenster oder Türen geöffnet sind
- Heizung herunterregeln wenn keiner zuhause / Hochfahren wenn jemand zuhause
- Alarmanlage scharf stellen, wenn keiner zuhause / deaktivieren wenn jemand zuhause
- Anwesenheitssimulation starten wenn keiner zuhause (Rollos hoch/ runterfahren, Licht an und ausschalten, etc)
- Haustüre abschließen, wenn keiner zuhause
Vielen Dank für Eure Hilfe!
ZitatHier der neue, funktionierende code aus der 99_myUtils.pm (falls es jemanden helfen sollte):
Es würde mit Sicherheit einem Anfänger helfen - nur leider wird dieser dein Beitrag nach hinten rutschen und die Nachkommenden werden nicht suchen.
Also wird auch deine gut gemeinte Dokumentation nichts helfen.
Warum ich das schreiben?
Weil ich vor ca. 2 Wochen grad einen Anfänger "begleitet" habe und ihm auch Log und $EVTPARTx gezeigt habe - es muss nur gesucht und gefunden werden (und es wird selten ersteres gemacht).
Da geb ich dir recht, nur ist es nicht immer so leicht (gerade als Anfänger) nach den richtigen Begriffen zu suchen.
Ich hatte z.B. garnicht gewusst das es $EVTPARTx gibt und versucht per perl zu Splitten. Wenn man ein wenig Programmiererfahrung hat geht man eben oft einen Weg der zunächst einfacher erscheint, tatsächlich aber doch einfacher zu Lösen ist.
Manchmal braucht man eben nur einen Schubs in die Richtige Richtung. Vielen dank jedenfalls für deinen Schubs ;)
Dann würde ich dich bitten dir einen "logischen" Titel zu überlegen.
Vielleicht schafft es dein Beitrag dann gefunden zu werden - ob er gesucht wird weiß ja dennoch niemand ;)
Deine Beiträge kannst du übrigens selbst bearbeiten und wenn deine Frage geklärt ist dann - bitte lies meinen angepinnten Beitrag hier im Anfängerbereich.
Wenn jeder Fragesteller seinem Beitrag einen "logischen" Betreff geben würde wäre die Suche auch einfacher :P