Wo finde ich die internen Timer-Events?

Begonnen von Reinerlein, 17 Februar 2013, 23:46:54

Vorheriges Thema - Nächstes Thema

Reinerlein

Hallo zusammen,

da ich leider im Development-Bereich keine Schreibrechte habe, mal hier...

Ich habe in meinem Sonos-Modul das Problem, dass ich Discover-Events eines Players manchmal mehrfach erhalte. Nun starte ich für jeden erkannten Player einen eigenen IsAlive-Timer, um zyklisch prüfen zu können, ob der Player noch da ist (der meldet sich leider nicht bei mir ab).

Nun habe ich versucht, bevor ich einen neuen Timer per "InternalTimer" eintrage, alle vorhergehenden Timer für denselben Player wieder zu entfernen.
Dazu wollte ich die Variable %main::intAt durchiterieren.
Leider ist diese immer leer, und es gibt nix zu iterieren, obwohl ich im Log sehe, dass die Events mehrfach ausgeführt werden, und somit auch eigentlich irgendwo drinstehen müssten...

Kann mir jemand sagen, welche Variable denn die richtige wäre, bzw. wie ich das sonst bewerkstelligen könnte?

Danke schon mal im voraus...

Grüße Reinerlein

Markus Bloch

Ganz einfach:


RemoveInternalTimer($hash);


Viele Grüße

Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Reinerlein

Hi Markus,

diese Prozedur ist für meine Zwecke leider zu grob. Dabei werden einfach "alle" Timer entfernt. Ich möchte aber nur bestimmte Timer (Unterscheidung erfolgt dann anhand der Parameter) entfernen.

Aus dieser Prozedur habe ich mir ja diese Hash-Variable herausgeholt, und meine eigene Prozedur geschaffen, die eben eine weitere Prüfung durchführen soll.
Ich habe in meiner Schleife eine Log-Ausgabe eingebaut, um festzustellen, welche Timer-Elemente ich durchlaufe, und ob meine Bedingungen passen.
Aber da kommt nie eine Ausgabe innerhalb der Schleife raus...

Vereinfacht beschrieben tut meine Prozedur folgendes (ohne den eigentlichen Lösch-Code):
foreach my $a (keys %main::intAt) {
  Log 1, 'RemoveInternalTimerByFunction.foreach: '.$a;
}

Damit sollte ich zumindest irgendeine Ausgabe erhalten, und ich kann mich dann dran machen, meine Lösch-Bedingungen zu formulieren und einzubauen.

Grüße Reinerlein

rudolfkoenig

RemoveInternalTimer loescht natuerlich nicht alle Timer, sondern nur die mit dem beim InternalTimer angegebenen Argument. Z.Bsp spezifiziert at das dazugehoerige %hash als Argument, damit kann es auch einfach loeschen.

Ausser %intAt gibt es keine Datenstrukturen fuer InternalTimer

Reinerlein

Hi Rudi,

irgendwie scheint man an diese Variable von meinem Modul aus nicht ranzukommen.
Ich habe jetzt die notwendige Einschränkung einfach in das Argument mit reinkodiert, und verwende die Original angebotene "RemoveInternalTimer"-Prozedur.

Damit klappt es jetzt. Danke nochmal für die Bestätigung, dass ich prinzipiell nichts übersehen habe :-)

Grüße Reinerlein

Dietmar63

Hallo Rudi, hallo Reinerlein,

Ich habe ein ähnliches Problem.
Ich habe ein Modul erstellt, das nutzt interne Timer.

Von der Logik in meinem Modul ist es so, dass sich zwei verschiedene nicht im Zusammenhang stehende Timerzyklen um irgndwelche Dinge kümmern.

Funktion A wird immer alle 30 Minuten aufgerufen.
Funktion B wird von zwei Zyklen immer alle 58 Minuten aufgerufen.

RemoveInternalTimer($hash); löscht jetzt leider immer alles - beispielsweise im define bei der Funktion modify.

Wie wäre es eine Funktion bereitzustellen, die nur die Timer verbunden mit funktion A löscht.
Dann entfällt das Problem, alle laufenden timer neu zu erstellen.

etwa so:


sub
RemoveInternalTimer($$)
{
  my ($mod, $fn) = @_;
  foreach my $a (keys %intAt) {
    delete($intAt{$a}) if($intAt{$a}{ARG} eq $mod && if($intAt{$a}{FN} eq $fn);
  }
}


nebenbei habe ich mir folgende Funkton gebaut. Liste alle InternalTimer auf:


#
sub printIntTimer() {

  my %cop;
  foreach my $a (keys %intAt) {

    my $nam = "";
    my $aaa = sprintf ("%6d",$a);
    my $arg = $intAt{$a}{ARG};
       $nam = %{$arg}->{NAME} if (ref($arg) eq "HASH" );
    my $tim = strftime('%d.%m.%Y %H:%M:%S',localtime($intAt{$a}{TRIGGERTIME}));
    my $func = sprintf ("%-25s %-25s",$nam,$intAt{$a}{FN});

    $cop{$nam." ".$aaa} = $aaa . " " . $tim . " " .  " " . $func ;
  }
  Log 3, "===============================================";
  foreach my $k (sort keys %cop) {
    Log 3, $cop{$k};
  }
}


vielleicht noch nicht schön aber ganz nützlich - habe bisher nichts ähnliches gefunden.
Wer ist für die Weiterentwicklung des Moduls zuständig?
Wer könnte das einbauen?
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

rudolfkoenig

> RemoveInternalTimer($hash); löscht jetzt leider immer alles - beispielsweise im define bei der Funktion modify.

Man ist ja nicht gezwungen es "falsch" zu machen :)
- falls define per modify aufgerufen wird, dann liegt im $hash->{OLDDEF} die alte Definition herum, man kann es also auswerten, und die Timer loeschen oder auch nicht.
- falls man 2 unterschiedliche Timer haben will, dann nimmt man fuer den ersten $hash, fuer den Zweiten baut man einen weiteren:
$hash->{timer2hash} = { mainHash => $hash };
InternalTimer("MeineFunktion", $hash->{timer2hash});

Falls die Zeiten der beiden Timer wichtig sind, dann kann man die im hash direkt menschenlesbar ablegen, dann sieht man die mit list. Falls nicht jeder es sehen soll, dann legt man die mit "." vorne im Namen ab.


>  Wer ist für die Weiterentwicklung des Moduls zuständig?

Modul? Fuer fhem.pl bin ich zustaendig.

Dietmar63

Zitat von: rudolfkoenig schrieb am Do, 28 Februar 2013 09:28> RemoveInternalTimer($hash); löscht jetzt leider immer alles - beispielsweise im define bei der Funktion modify.
...
- falls man 2 unterschiedliche Timer haben will, dann nimmt man fuer den ersten $hash, fuer den Zweiten baut man einen weiteren:
$hash->{timer2hash} = { mainHash => $hash };
InternalTimer("MeineFunktion", $hash->{timer2hash});

Falls die Zeiten der beiden Timer wichtig sind, dann kann man die im hash direkt menschenlesbar ablegen, dann sieht man die mit list. Falls nicht jeder es sehen soll, dann legt man die mit "." vorne im Namen ab.
...

Gut dass ich gefragt habe.
Auf diese einfache Lösung mit mehreren Hash wäre ich nicht gekommen.
Manchmal sieht man den Wald vor Bäumen nicht.
Danke!
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Dietmar63

Falls die Zeiten der beiden Timer wichtig sind, dann kann man die im hash direkt menschenlesbar ablegen, dann sieht man die mit list. Falls nicht jeder es sehen soll, dann legt man die mit "." vorne im Namen ab.

das habe ich noch nicht wirklich verstanden. Meine obige Routine liefert folgenden Output.
Twilight hat bei mir 3 Timer. Wie könnte ich die mit list ausgeben. Könnte man list erweitern?:

2013.02.28 00:18:06 3:    198 28.02.2013 17:54:05  ZufallsTimerTv            RandomTimer_Exec        
2013.02.28 00:18:06 3:    197 28.02.2013 18:12:23  ZufallsTimerTisch         RandomTimer_Exec        
2013.02.28 00:18:06 3:    194 28.02.2013 05:16:01  Twilight                  Twilight_GetUpdate_nextEvent
2013.02.28 00:18:06 3:    193 28.02.2013 16:36:20  Twilight                  Twilight_GetUpdate_Wea  
2013.02.28 00:18:06 3:    192 28.02.2013 06:28:37  Twilight                  Twilight_GetUpdate_Wea  
2013.02.28 00:18:06 3:     15 28.02.2013 02:00:00  StehlampenAus             at_Exec                  
2013.02.28 00:18:06 3:    196 01.03.2013 00:00:00  StehlampeTischAus         at_Exec                  
2013.02.28 00:18:06 3:     10 28.02.2013 17:52:43  StehlampeTischAn          at_Exec                  
2013.02.28 00:18:06 3:     11 28.02.2013 17:52:48  StehlampeTVAn             at_Exec                  
2013.02.28 00:18:06 3:     19 28.02.2013 05:40:00  PumpeTimer                at_Exec                  
2013.02.28 00:18:06 3:    206 28.02.2013 00:19:34  NAS                       WOL_UpdateReadings      
2013.02.28 00:18:06 3:     18 28.02.2013 03:00:00  HifianlageAus             at_Exec                  
2013.02.28 00:18:06 3:     16 28.02.2013 12:00:00  HifianlageAnWeekend       at_Exec                  
2013.02.28 00:18:06 3:     17 28.02.2013 18:00:00  HifianlageAnWeekday       at_Exec                  
2013.02.28 00:18:06 3:     63 28.02.2013 15:00:00  HeizungWohnen_wt          Heating_Control_Update  
2013.02.28 00:18:06 3:     62 28.02.2013 12:00:00  HeizungWohnen_we          Heating_Control_Update  
2013.02.28 00:18:06 3:      7 28.02.2013 04:05:00  HeizungWohnenWecker       at_Exec                  
2013.02.28 00:18:06 3:      9 28.02.2013 04:35:00  HeizungWohnenSync         at_Exec                  
2013.02.28 00:18:06 3:     26 28.02.2013 05:35:00  HeizungKueche_wt          Heating_Control_Update  
2013.02.28 00:18:06 3:     27 28.02.2013 06:45:00  HeizungKueche_we          Heating_Control_Update  
2013.02.28 00:18:06 3:      6 28.02.2013 04:00:00  HeizungKuecheWecker       at_Exec                  
2013.02.28 00:18:06 3:      8 28.02.2013 04:30:00  HeizungKuecheSync         at_Exec                  
2013.02.28 00:18:06 3:    201 01.03.2013 00:01:00  DayCare                   at_Exec                  
2013.02.28 00:18:06 3:    219 28.02.2013 00:18:12                            FW_closeOldClients      
2013.02.28 00:18:06 3:    199 01.03.2013 00:00:02                            holiday_refresh          
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

rudolfkoenig

Ich meinte mit meinem Vorschlag das eigene Modul, bzw. jedes Modul muesste solche timer selbst in dem eigenen Hash verewigen. Ich sehe dafuer keine generelle Notwendigkeit.

Dietmar63

Das mit den zwei hashes habe ich schon verstanden. Ich sehe keine Notwendigkeit für eine zweite Funktion removeinternaltimer mehr.

Aber wie komme ich mit existierenden Mitteln an die internaltimer heran.

Ich hatte dich so verstanden, dass es mit list geht - aber wie?
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

rudolfkoenig

>  Aber wie komme ich mit existierenden Mitteln an die internaltimer heran.

Gar nicht. Ist ja auch Internal.

Reinerlein

Hi,

Rudi meinte wohl, dass du dir die Informationen bzgl. deines Timers wohl zusätzlich in den Device-Hash legen kannst, und diese Info dann mit List auch ausgegeben wird, oder?

Aber damit sind wir auch beim Kern der eigentlichen Geschichte:
Könnte man nicht die Variable "%intAt" (die die internen Timer in fhem.pl hält), nach aussen zugreifbar machen?

In meinen Tests hat das mit meiner eigenen RemoveTimer-Function geklappt, wenn in fhem.pl diese Variable (wie auch z.B. %defs) nicht als "my" deklariert ist, sondern als "use vars qw(%intAt);".
Damit könnte man sich eigene Lösch-Logiken im Modul bauen. Ich hatte mir z.B. eine gebaut, die Timer mit einer bestimmten Funktion und bestimmten Parametern löscht. Da meine Funktionsnamen FHEM-weit eindeutig sind (diese enthalten das Modul-Kürzel vorangestellt), sollte das kein Problem darstellen.
Leider kommt man an diese Timer-Variable ja nicht ran...

Grüße Reinerlein