In meinem HOMEMODE Modul startet das Update der Internals erst nach "global:INITIALIZED" damit ich sicher gehen kann dass bereits alle von HOMEMODE zu überwachenden Geräte geladen wurden.
Seit dem heutigen FHEM Update kommt aber genau dieses Event zu früh!
Ich habe mal eine Log Ausgabe bei "global:INITIALIZED" mit eingebaut.
Hier mal der Log Mitschnitt beim Start:
2017.04.21 10:27:48 0: Server shutdown
2017.04.21 10:27:50 3: telnetPort: port 7072 opened
2017.04.21 10:27:50 3: WEB: port 8083 opened
2017.04.21 10:27:50 2: eventTypes: loaded 1272 events from ./log/eventTypes.txt
2017.04.21 10:27:50 3: Opening tvll device 127.0.0.1:19444
2017.04.21 10:27:50 3: DbLog logdb: Creating Push-Handle to database mysql:database=fhem;host=localhost;port=3306 with user fhemuser
2017.04.21 10:27:50 3: DbLog logdb: Push-Handle to db mysql:database=fhem;host=localhost;port=3306 created
2017.04.21 10:27:50 3: eq3: Defined with URL http://www.eq-3.de/service/downloads.html and interval 86400
2017.04.21 10:27:50 3: eq3: added hint :text,reading,internal,expression,delete to attr readingMaxAgeReplacementMode in userattr list
2017.04.21 10:27:50 3: TABLETUI: new ext defined infix:ftui/: dir:./www/tablet/:
2017.04.21 10:27:50 3: Registering HTTPSRV TABLETUI for URL /ftui and assigned link ftui/ ...
Use of uninitialized value in string eq at fhem.pl line 2837.
2017.04.21 10:27:50 3: HOMEMODE_updateInternals
2017.04.21 10:27:50 2: Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät rgr_Residents
2017.04.21 10:27:50 2: SecurityCheck: WEB has no associated allowed device with basicAuth. telnetPort has no associated allowed device with password/globalpassword. Restart FHEM for a new check if the problem is fixed, or set the global attribute motd to none to supress this message.
2017.04.21 10:27:50 0: Featurelevel: 5.8
2017.04.21 10:27:50 0: Server started with 78 defined entities (fhem.pl:14046/2017-04-20 perl:5.020002 os:linux user:fhem pid:1921)
HOMEMODE_updateInternals wird nun also bereits aufgerufen bevor FHEM komplett initialisiert ist. :-\
Wollte das Modul eigentlich heute Abend in SVN einchecken, aber so wird das nix... ???
Gruß
Dan
Und woran sieht man, dass es zu frueh ist?
Kannst du es bitte mit "attr global verbose 5" und Kommentaren belegen? So in der Art: schau mal, dieses Befehl wird hier noch aus fhem.cfg/fhem.state gelesen, nachdem meine Routine mit "global:INITIALIZED" aufgerufen wurde?
2017.04.21 10:27:50 3: HOMEMODE_updateInternals
2017.04.21 10:27:50 2: Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät rgr_Residents
Als Erstes werden die ROOMMATE/GUEST Devices von HOMEMODE "eingelesen".
Diese sind aber scheinbar noch nicht definiert wie die zweite Logzeile anzeigt.
Es werden leider gar keine Devices mehr von HOMEMODE gefunden, da HOMEMODE nach allen Devices in der cfg steht.
Verbose per FHEMWEB auf 5 setzen geht nicht! Es kommt die Fehlermeldung aus dem angehängten Screenshot.
Per "attr global verbose 5" ging es nun.
Das Log passt hier nicht komplett rein. Habe es nun als txt angehangen.
Bis heute morgen vor dem Update ging das noch einwandfrei.
Gruß
Dan
ZitatVerbose per FHEMWEB auf 5 setzen geht nicht!
Bei mir schon, hat vermutlich mit dem vorhin gefixten Bug was zu tun.
ZitatDiese sind aber scheinbar noch nicht definiert wie die zweite Logzeile anzeigt.
Scheinbar ist mir nicht ausreichend. In deinem Log kommt nach der Fehlermeldung:
Zitat2017.04.21 11:46:49 3: HOMEMODE_updateInternals
2017.04.21 11:46:49 2: Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät rgr_Residents
2017.04.21 11:46:49 5: Triggering n_INITIALIZED
2017.04.21 11:46:49 4: n_INITIALIZED exec set d_init on
2017.04.21 11:46:49 5: Cmd: >set d_init on<
2017.04.21 11:46:49 4: dummy set d_init on
2017.04.21 11:46:49 5: Starting notify loop for d_init, 1 event(s), first is on
2017.04.21 11:46:49 5: ABFALL_Notify(Abfall) - Device: d_init
2017.04.21 11:46:49 5: End notify loop for d_init
2017.04.21 11:46:49 5: End notify loop for global
2017.04.21 11:46:49 2: SecurityCheck: WEB has no associated allowed device with basicAuth. telnetPort has no associated allowed device with password/globalpassword. Restart FHEM for a new check if the problem is fixed, or set the global attribute motd to none to supress this message.
2017.04.21 11:46:49 0: Featurelevel: 5.8
2017.04.21 11:46:49 0: Server started with 78 defined entities (fhem.pl:14046/2017-04-20 perl:5.020002 os:linux user:fhem pid:2070)
Ich sehe keine weiteren Definitionen / Attribute / etc.
Wie es zusammenhängt ist mir bisher auch noch ein Rätsel.
Sollte das INITIALIZED Event nicht aber nach "Server started with 78 defined entities" kommen?
Wieso ging es bis heute früh und ohne Änderung an meinem Modul auf einmal nicht mehr?
Gruß
Dan
Dachte gerade ich lasse mal sicherheitshalber ein "update force" drüber laufen, aber das funktioniert nicht.
Die Seite rödelt ewig um dann in "weiß" stehen zu bleiben.
Irgendwas ist doch hier im "Brötchen"...
Gruß
Dan
Bei mir funktioniert update.
Habe nun das Log beobachtet!
FHEM blockiert komplett während "update force" und zeigt auch keinen Event-Monitor/Log an wie bei "update".
"update force" ist aber durchgelaufen, trotz weißer Seite am Ende.
Leider trotzdem selbes Verhalten.
INITIALIZED ruft HOMEMODE_updateInternals auf.
sub HOMEMODE_Notify($$)
{
my ($hash,$dev) = @_;
my $name = $hash->{NAME};
my $devname = $dev->{NAME};
my $devtype = $dev->{TYPE};
return if (AttrVal($name,"disable",0) == 1);
my $events = deviceEvents($dev,1);
if (grep(/^INITIALIZED$/,@{$events}))
{
Debug Dumper @{$events};
Debug $init_done;
Log3 $name,3,"HOMEMODE_updateInternals";
HOMEMODE_updateInternals($hash);
}
In HOMEMODE_updateInternals werden als Erstes von RESIDENTS die ROOMMATE/GUEST aus dem Hash gelesen, diese sind aber noch leer.
sub HOMEMODE_updateInternals($;$)
{
my ($hash,$force) = @_;
$HOMEMODE_de = 1 if (AttrVal("global","language","EN") eq "DE");
my $name = $hash->{NAME};
my $resdev = $hash->{DEF};
my $trans;
if (!IsDevice($resdev))
{
$trans = $HOMEMODE_de?
"$resdev ist nicht definiert!":
"$resdev is not defined!";
$hash->{STATE} = $trans;
}
elsif (!IsDevice($resdev,"RESIDENTS"))
{
$trans = $HOMEMODE_de?
"$resdev ist kein gültiges RESIDENTS Gerät!":
"$resdev is not a valid RESIDENTS device!";
$hash->{STATE} = $trans;
}
else
{
my @oldMonitoredDevices = @{$hash->{helper}{allMonitoredDevices}} if ($hash->{helper}{allMonitoredDevices});
delete $hash->{helper}{allMonitoredDevices};
delete $hash->{helper}{presdevs};
delete $hash->{RESIDENTS};
delete $hash->{SENSORSCONTACT};
delete $hash->{SENSORSMOTION};
delete $hash->{SENSORSENERGY};
delete $hash->{SENSORSLUMINANCE};
$hash->{VERSION} = $HOMEMODE_version;
my @residents;
push @residents,$defs{$resdev}->{ROOMMATES} if ($defs{$resdev}->{ROOMMATES});
push @residents,$defs{$resdev}->{GUESTS} if ($defs{$resdev}->{GUESTS});
Debug $defs{$resdev}->{ROOMMATES};
Debug Dumper @residents;
if (scalar @residents < 1)
{
$trans = $HOMEMODE_de?
"Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät $resdev":
"No available ROOMMATE/GUEST in RESIDENTS device $resdev";
Log3 $name,2,$trans;
readingsSingleUpdate($hash,"HomeInfo",$trans,1);
return;
}
else
{
$hash->{RESIDENTS} = join(",",@residents);
}
2017.04.21 13:46:11 1: DEBUG>$VAR1 = 'INITIALIZED';
2017.04.21 13:46:11 1: DEBUG>1
2017.04.21 13:46:11 3: HOMEMODE_updateInternals
Use of uninitialized value $msg in concatenation (.) or string at fhem.pl line 4576.
2017.04.21 13:46:11 1: DEBUG>
2017.04.21 13:46:11 1: DEBUG>
2017.04.21 13:46:11 2: Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät rgr_Residents
Führe ich HOMEMODE_updateInternals nochmal aus nachdem dann FHEM wirklich richtig läuft funktioniert es wieder.
2017.04.21 13:46:49 1: DEBUG>rr_Brina,rr_Dan
2017.04.21 13:46:49 1: DEBUG>$VAR1 = 'rr_Brina,rr_Dan';
$VAR2 = 'rg_Gast,rg_Mutter,rg_SBert';
Gruß
Dan
Habe es weiter eingrenzen können.
Es liegt scheinbar an RESIDENTS.
Durch die umfangreichen Umbauarbeiten an RESIDENTS in letzter Zeit muss sich etwas verändert haben.
Es sind jedenfalls nach INITIALIZED noch keine ROOMMATE/GUEST im Hash verfügbar.
Muss ich jetzt wirklich einen InternalTimer einbauen um HOMEMODE_updateInternals zu verzögern?
Gruß
Dan
Vielleicht läuft RESIDENTS inzwischen auch erst los, nachdem global:INITIALIZED erfolgt ist?
Wir hatten hier doch in den letzten Wochen die Grundsatzdiskussion, dass bestimmte Module erst nach bestimmten Kriterien starten dürfen, um von ihrer Reihenfolge innerhalb der Konfigurationsdaten unabhängig zu werden.
wenn mehrere module die voneinander abhängig sind auf global:INITIALIZED warten haben wir ein problem da die reihenfolge dieser module untereinander nicht definiert bzw. alphabetisch ist.
im prinzip kann man seine eigene notify order ändern, das funktioniert aber nur wenn es zwischen diesen modulen regeln gibt und nicht jeder für sich versucht möglichst weit hinten zu sein.
vielleicht wäre es besser wenn es eine art modul spezifisches initialized event gäbe um diese abhängigkeit zu entkoppeln.
Danke für Eure Hinweise.
Dank Julians Hinweis (https://forum.fhem.de/index.php/topic,19040.msg624083.html#msg624083) konnte ich mit:
$hash->{NotifyOrderPrefix} = "51-";
zumindest erst mal sicherstellen dass die ROOMMATE/GUEST Devices wieder vorhanden sind.
Jetzt muss ich "nur" wieder alles testen worauf sich das evtl. noch in meinem Modul auswirkt.
Nur gut dass das vor dem SVN Check-in passiert ist... 8)
Gruß
Dan
Hi,
und wo genau ist jetzt das Problem, einfach das hier hinzuschreiben:
InternalTimer (gettimeofday(), 'HOMEMODE_updateInternals', $hash);
Das verzögert das ganze bis alles geladen ist.
Gruß,
Thorsten
Zitat von: betateilchen am 21 April 2017, 18:18:57
Vielleicht läuft RESIDENTS inzwischen auch erst los, nachdem global:INITIALIZED erfolgt ist?
Genau. Stand schon seit 2 Jahren auf der Todo... ;)
Jetzt hatte ich mal einen Grund das anzupacken (allerdings hab ich von einer Grundsatzdiskussion nichts mitbekommen...).
@Thorsten Pferdekaemper: das geht nicht. weil es auf eine definierte reihenfolge ankommt funktioniert eine einfache verzögerung nicht da damit die reihenfolge zufällig (bzw. alphabetisch vom modul namen) abhängt.
gruss
andre
Zitat von: Loredo am 21 April 2017, 19:59:05
Genau. Stand schon seit 2 Jahren auf der Todo... ;)
Jetzt hatte ich mal einen Grund das anzupacken (allerdings hab ich von einer Grundsatzdiskussion nichts mitbekommen...).
Na gut dass das jetzt zur Sprache kommt. ;)
Zitat von: betateilchen am 21 April 2017, 18:18:57
Wir hatten hier doch in den letzten Wochen die Grundsatzdiskussion, dass bestimmte Module erst nach bestimmten Kriterien starten dürfen, um von ihrer Reihenfolge innerhalb der Konfigurationsdaten unabhängig zu werden.
Genau deshalb dachte ich man wäre "safe" bei INITIALIZED!
Bisher tut das Ändern der NTFY_ORDER ihren Dienst. Es sind aber leider erstmal längerfristige Tests nötig. :(
Ich setzte das Thema mal auf gelöst, damit Rudi wieder "in Ruhe schlafen" kann. ;)
Danke mal wieder für Deine Unterstützung Rudi!
Zitat von: justme1968 am 21 April 2017, 18:36:52
wenn mehrere module die voneinander abhängig sind auf global:INITIALIZED warten haben wir ein problem da die reihenfolge dieser module untereinander nicht definiert bzw. alphabetisch ist.
im prinzip kann man seine eigene notify order ändern, das funktioniert aber nur wenn es zwischen diesen modulen regeln gibt und nicht jeder für sich versucht möglichst weit hinten zu sein.
vielleicht wäre es besser wenn es eine art modul spezifisches initialized event gäbe um diese abhängigkeit zu entkoppeln.
Bleibt nur die Frage offen wie man das "Problem" längerfristig angehen könnte...
Danke an alle.
Gruß
Dan
P.S. Wenn es der allgemeinen Problematik hilft darf hier natürlich gern weiter darüber diskutiert werden. ;)
EDIT: P.P.S. Hier sieht man mal wieder wie wertvoll eine aktive Entwickler Community ist. :)
Zitat von: justme1968 am 21 April 2017, 20:00:07
@Thorsten Pferdekaemper: das geht nicht. weil es auf eine definierte reihenfolge ankommt funktioniert eine einfache verzögerung nicht da damit die reihenfolge zufällig (bzw. alphabetisch vom modul namen) abhängt.
Ja, ist klar... Ich hab's mir jetzt nochmal genauer angeschaut und es lief ja sowieso schon in einem notify. Da ist natürlich die InternalTimer-Lösung Schwachsinn. (Ich beleidige damit nur mich selbst, bevor jetzt die Popcorn-Party losgeht.)
Da wäre dann tatsächlich ein Modul-spezifisches Event notwendig. Da aber FHEM selbst (also fhem.pl) nicht wissen kann, inwiefern welches Modul welche Verzögerungs-Technik verwendet, kann das wirklich nur jedes Modul selbst machen. Ich kann mir da nichts generisches vorstellen. Höchstens vielleicht eine Regel, wie das Event aussehen sollte.
Gruß,
Thorsten
genau. eine regel wie das event ausschauen sollte.
Zitatgenau. eine regel wie das event ausschauen sollte.
Vorschlag: wenn ein Modul seine Konfiguration per global:INITIALIZED oder InternalTimer beendet, dann muss es ein Event "global:<MODUL> INITIALIZED" oder "global:<DEVICE> INITIALIZED" generieren, dann kann man sich an diese Events haengen. Weiterhin ungeloest: warten bis alle fertig sind.
und vor allem, wann ein solcher event erfolgen soll...
- in xxx_Initialize() macht es wenig Sinn, weil das initialize() alleine noch lange nix mit den devices zu tun hat
- in xxx_Define() macht es auch wenig Sinn, weil das Modul ja gar nicht weiß, wieviele Geräte während des Ladens der FHEM-Konfiguration insgesamt angelegt werden müssen. Ein event macht erst dann Sinn, wenn das letzte Gerät definieirt ist.
- und auch dann wird es schwierig, weil manche Geräte, die per Netzwerk-Discovery gefunden werden müssen, ziemlich lange brauchen.
Es müsste also nach dem globalen $init_done (bzw. global:INITIALIZED) jedes Modul entsprechend prüfen, ob es mit seiner eigenen Initialisierung fertig ist und erst danach seine eigene Fertigmeldung erzeugen.
Ob man das Ganze über ein event steuern sollte - ich bin mir nicht sicher.
$modules{<modulName>}{initdone}=1
als Fertigmeldung wäre vielleicht eine Alternative, die irgendwie ausgewertet werden könnte (und müsste).
Zitat von: DeeSPe am 21 April 2017, 20:23:30
Genau deshalb dachte ich man wäre "safe" bei INITIALIZED!
Jetzt, wo es "alle" anfangen zu nutzen, eben dann nicht mehr so pauschal, wenn man sich darauf verlässt, dass ein bestimmtes Modul fertig initialisiert ist.
Ich werde mal noch einen DoTrigger() in die Module selbst einbauen, so dass diese selbst nach Erledigung das globale Event nochmals mit dem Zusatz des Devicenamens rausschicken. Dann kann man auch explizit darauf triggern, unabhängig von NotifyOrderPrefix.
Zitat von: betateilchen am 21 April 2017, 20:38:50
$modules{<modulName>}{initdone}=1
Im %modules Hash ist es nicht richtig aufgehoben, da gibt es auch schon LOADED. Da du aber auf Device-Ebene benachrichtigt werden willst, gehört es ins Device Hash.
Ich werde $hash->{.READY}=1 setzen.
@rudi: ja. das finde ich gut.
braucht man ein 'alle fertig' ?
je nach definition gibt es das vielleicht sogar garnicht. es können ja auch zur laufzeit beliebig devices dazu kommen.
so lange man richtig auf die events reagiert wäre das ja auch kein problem.
@betateilchen: das wann ist einfach. wenn das modul meint es ist fertig. ob das nach dem start aus NotifyFn kommt oder zur laufzeit aus DefFn oder irgendwann später wenn ein neues device dazu kommt hängt vom modul ab.
ich glaube der knackpunkt ist: das event ist eigentlich kein INITIALIZED sondern ein CONFIG_CHANGED. d.h. es wird nicht nur beim start ein mal erzeugt sondern immer dann wenn sich intern etwas geändert hat und abhängige module benachrichtig werden. also z.b. auch zur laufzeit wenn RESIDENTS zur laufzeit ein neues ROOMATE device inkludiert.
ob ein device überhaupt so ein event erzeugt hängt auch davon ab ob es überhaupt ein abhängiges device gibt. wenn also jemand kommt und sagt 'es wäre schön wenn device xy so ein event erzeugt damit ich mich dran hängen kann'.
Zitat von: Loredo am 21 April 2017, 20:48:15
Im %modules Hash ist es nicht richtig aufgehoben, da gibt es auch schon LOADED. Da du aber auf Device-Ebene benachrichtigt werden willst, gehört es ins Device Hash.
Ich werde $hash->{.READY}=1 setzen.
Und woher weiß ein "abhängiges" Modul dann, dass
alle devices vom TYPE=<module> angelegt sind?
Zitat von: betateilchen am 21 April 2017, 20:53:19
Und woher weiß ein "abhängiges" Modul dann, dass alle devices vom TYPE=<module> angelegt sind?
Gegenfrage: Woher soll das mein Modul wissen?
Zitat von: justme1968 am 21 April 2017, 20:49:05
ich glaube der knackpunkt ist: das event ist eigentlich kein INITIALIZED sondern ein CONFIG_CHANGED. d.h. es wird nicht nur beim start ein mal erzeugt sondern immer dann wenn sich intern etwas geändert hat und abhängige module benachrichtig werden. also z.b. auch zur laufzeit wenn RESIDENTS zur laufzeit ein neues ROOMATE device inkludiert.
ob ein device überhaupt so ein event erzeugt hängt auch davon ab ob es überhaupt ein abhängiges device gibt. wenn also jemand kommt und sagt 'es wäre schön wenn device xy so ein event erzeugt damit ich mich dran hängen kann'.
Genau das ist der Punkt warum es in meinem Modul "set <name> updateInternalsForce" gibt. Wenn sich ein überwachter TYPE erweitert/verringert dann muss eben genau das ausgeführt werden damit die Device aktualisiert werden ohne Neustart.
Ich fand auch keinen Weg das zu automatisieren, ausser einer zeitgesteuerten Funktion.
Gruß
Dan
Ich habe für RESIDENTS+ROOMMATE+GUEST jetzt eingecheckt:
1. Event "INITIALIZED devicename", nachdem das Device sich intern fertig initialisiert hat
2. Event "MODIFIED devicename", nachdem das Device eine interne Änderung durchgeführt hat
$hash->{'.READY'} wird intern verwendet und steht während des Initialisierens solange auf 0, bis diese erstmalig abgeschlossen wurde.
Zitat von: DeeSPe am 21 April 2017, 21:05:12
Ich fand auch keinen Weg das zu automatisieren, ausser einer zeitgesteuerten Funktion.
Da wäre eine Kooperation ja sinnvoll gewesen. Kann es mir nicht verkneifen nochmals darauf hinzuweisen, dass du auf meine Bitte sich abzustimmen damals nicht reagiert hast. ::)
Zitat von: Loredo am 21 April 2017, 21:23:29
Da wäre eine Kooperation ja sinnvoll gewesen. Kann es mir nicht verkneifen nochmals darauf hinzuweisen, dass du auf meine Bitte sich abzustimmen damals nicht reagiert hast. ::)
Ach schön, hatte nur auf Deinen erneuten Hinweis gewartet. Danke dass Du meine Erwartung erfüllt hast! 8)
Das hat ja nun aber wirklich nichts speziell mit Deinem Modul zu tun. HOMEMODE überwacht noch andere Devices bei denen es mir so ähnlich gehen könnte,
ROOMMATE RESIDENTS ist nun aber mal das initial nötige Device. Wenn ich z.B. einen Zwischenstecker gleichen Specs dazu nehme, gibt es bisher auch keine Möglichkeit zur Laufzeit automatisch darauf zu reagieren.
Ich schaue mir mal an was Du da gemacht hast Julian.
Vielleicht klappt es ja doch noch mit einer Abstimmung. ;)
Gruß
Dan
Zitat von: Loredo am 21 April 2017, 21:21:48
1. Event "INITIALIZED devicename", nachdem das Device sich intern fertig initialisiert hat
2. Event "MODIFIED devicename", nachdem das Device eine interne Änderung durchgeführt hat
mit oder ohne Modulbezug im event? (ich gebe zu, aus Bequemlichkeit habe ich jetzt nicht in die Moduldatei geschaut)
Da Deine drei Module nicht die einzigen in FHEM sind, sollte man irgendwie unterscheiden können, woher ein event kommt.
Deshalb fände ich
RESIDENTS:INITIALIZED <deviceName>
sinnvoller als nur
INITIALIZED <deviceName>
Zitat von: betateilchen am 21 April 2017, 21:46:43
mit oder ohne Modulbezug im event? (ich gebe zu, aus Bequemlichkeit habe ich jetzt nicht in die Moduldatei geschaut)
Ohne, denn es geht rein um die einzelne Device-Instanz selbst. Warum brauche ich da den Modulnamen davor?
Wir reden hier ja ohnehin davon, dass per NOTIFYDEV eingeschränkt wird, welche Events ich erhalte, oder nicht?
------
Mit einem weiteren Patch habe ich jetzt ein weiteres Event eingebaut, welches tatsächlich dann triggert, wenn alle Devices des Moduls fertig initialisiert wurden:
<TYPE> INITIALIZED
Das entspricht Rudis Vorschlag dafür.
Dieses Event löst schließlich nochmals je Device das zuvor eingebaute Event aus in dem Format:
INITIALIZED <device>
Diese Events werden nach einem rereadcfg entsprechend wiederholt.
Wenn ein einzelnes Device zur Laufzeit geändert wird, erzeugt es das Event CONFIG_CHANGED:
CONFIG_CHANGED <device>
Ich hatte zunächst gedacht, dass man hier auch "MODIFIED <device>" schicken könnte, wollte es aber dann während der Laufzeit doch unterscheidbar haben.
Zitat von: Loredo am 21 April 2017, 23:39:40
Ohne, denn es geht rein um die einzelne Device-Instanz selbst. Warum brauche ich da den Modulnamen davor?
Wir reden hier ja ohnehin davon, dass per NOTIFYDEV eingeschränkt wird, welche Events ich erhalte, oder nicht?
Nein, in EnOcean werden alle Events überwacht, da dort auch bei Bedarf Events von Referenzdevices anderer Module ausgewertet werden müssen, z. B. Temperaturwerte von Raumthermostaten anderer Protokollfamilien.
Zitatin EnOcean werden alle Events überwacht, da dort auch bei Bedarf Events von Referenzdevices anderer Module ausgewertet werden müssen
Ich hoffe aber stark, dass das erstens optional und zweitens per NOTIFYDEV (bzw. notifyRegexpChanged) eingeschraenkt auf das per Befehl/Attribut/etc vom Benutzer spezifizierte Geraet ist. Meiner Ansicht nach waere aber sowas (Koppelung mehrerer Geraete) trotzdem nicht die Aufgabe von einem Modul wie EnOcean. Falls ich was nicht verstehe, bitte mich aufzuklaeren.
Zitat von: rudolfkoenig am 22 April 2017, 08:39:39
Ich hoffe aber stark, dass das erstens optional und zweitens per NOTIFYDEV (bzw. notifyRegexpChanged) eingeschraenkt auf das per Befehl/Attribut/etc vom Benutzer spezifizierte Geraet ist. Meiner Ansicht nach waere aber sowas (Koppelung mehrerer Geraete) trotzdem nicht die Aufgabe von einem Modul wie EnOcean. Falls ich was nicht verstehe, bitte mich aufzuklaeren.
Nein, es ist nicht eingeschränkt. Bisher habe ich dafür keine brauchbare Lösung gefunden.
Was Aufgabe eines Modules wäre und was übergreifende Routinen besser übernehmen könnten, darüber wird hier ununterbrochen meist ohne konkretes Ergebnis diskutiert. Ich beteilige mich nicht mehr an diesen fruchtlosen Debatten.
Ich habe jedenfalls keine Ambitionen einem Anwender z. B. zu erklären, dass er einen Temperaturwert, den er mit einem Homematik-Sensor erfasst, nicht oder nur umständlich über ein Notify zur Steuerung eines EnOcean-Heizkörperventils verwenden kann.
Aber genau so ein umstaendliches notify unterscheidet FHEM von einem zusammengeloetetes Fertiggeraet.
Zitat von: Loredo am 21 April 2017, 23:39:40
Ohne, denn es geht rein um die einzelne Device-Instanz selbst. Warum brauche ich da den Modulnamen davor?
Wir reden hier ja ohnehin davon, dass per NOTIFYDEV eingeschränkt wird, welche Events ich erhalte, oder nicht?
Nein. Du solltest einfach mal über den Tellerrand Deiner eigenen Module hinausschauen.
Hier gibt es die erste Diskussion über die neue event-Flut
https://forum.fhem.de/index.php/topic,70932.0.html
Zitat von: betateilchen am 22 April 2017, 12:21:49
Hier gibt es die erste Diskussion über die neue event-Flut
So what...
Wir haben jetzt
global:INITIALIZED
global:<TYPE> INITIALIZED
global:INITIALIZED <device>
Ich finde das ist "unordentlich".
Vorschlag:
global:INITIALIZED
global:INITIALIZED <TYPE>
global:INITIALIZED <TYPE> <device>
ja. ich finde auch das diese version aufgeräumter ist.
ja, aufgeräumt ist das wohl.
Allerdings verstehe ich nicht, warum da ein "global" am Anfang stehen soll, denn ein von RESIDENTS erzeugter event hat doch überhaupt nix mit dem device "global" zu tun.
bei den letzen beiden könnte man auch den TYPE nach vorne an stelle von global ziehen. also so:
Zitatglobal:INITIALIZED
<TYPE>:INITIALIZED
<TYPE>:INITIALIZED <device>
diese events kommen dann aber nicht mehr durch den longpoll filter wenn man diesen eingeschränkt hat. ich weiß nicht ob das relevant ist.
Ein Event muss an einem Geraet haengen, ein DoTrigger(<TYPE>,"INITIALIZED") waere also nicht moeglich. Neuer Vorschlag:
global:INITIALIZED
global:INITIALIZED <TYPE>
<device>:INITIALIZED
<device>:INITIALIZED
ist nicht gut da man dann den device namen kennen muss oder jedes mal den type nachschauen muss.
dann lieber den ursprünglichen vorschlag:global:INITIALIZED
global:INITIALIZED <TYPE>
global:INITIALIZED <TYPE> <device>
Ich finde die Ideen mit global:INITIALIZED ehrlich gesagt nicht gut.
Es können ungewünschte Nebenwirkungen auftreten wenn in bestehenden Modulen nur auf /^INITIALIZED/ statt auf /^INITIALIZED$/ geprüft wird.
Ich finde global:INITIALIZED sollte nicht angetastet werden.
Statt dessen finde ich persönlich
<device/type>:INITIALIZED
besser.
Gruß
Dan
was würde dagegen sprechen events von <TYPE> zu erlauben?
CHANGED haengt im $defs{devicename}.
{ DoTrigger( "global", "INITIALIZED XXXXXXX", 1 ) }
Probiert's mal bei Euch aus!
Ich sehe schon evtl. aufkommende Schwierigkeiten im Event Monitor / Log.
Gruß
Dan
Zitat von: betateilchen am 22 April 2017, 13:29:02
Allerdings verstehe ich nicht, warum da ein "global" am Anfang stehen soll, denn ein von RESIDENTS erzeugter event hat doch überhaupt nix mit dem device "global" zu tun.
Weil man es sonst nicht von einem STATE Event unterscheiden kann.
Zitat von: justme1968 am 22 April 2017, 13:53:37
<device>:INITIALIZED
ist nicht gut da man dann den device namen kennen muss oder jedes mal den type nachschauen muss.
Genau. Man kann da nicht sicher unterscheiden, ob davor jetzt ein Devicename oder ein Modulname steht.
Zitat von: DeeSPe am 22 April 2017, 13:59:18
Es können ungewünschte Nebenwirkungen auftreten wenn in bestehenden Modulen nur auf /^INITIALIZED/ statt auf /^INITIALIZED$/ geprüft wird.
Da bin ich anderer Meinung. Das globale Event ist als ^INITIALIZED$ deklariert. Wer nach ^INITIALIZED filtert, hat unsauber gearbeitet.
Zitat von: rudolfkoenig am 22 April 2017, 13:49:13
Neuer Vorschlag:
global:INITIALIZED
global:INITIALIZED <TYPE>
<device>:INITIALIZED
Die dann wohl beste Lösung.
Zitat von: rudolfkoenig am 22 April 2017, 13:11:13
Wir haben jetzt
global:INITIALIZED
global:<TYPE> INITIALIZED
global:INITIALIZED <device>
Ich finde das ist "unordentlich".
Gedacht war eigentlich, dass ein Modul seinen eigenen globalen Scope bekommt, um ggf. auch andere Events als INITIALIZED nutzen zu können (nicht dass ich das derzeit vor hätte). Deshalb sollte das Event mit dem Modulnamen beginnen, wenn es das Modul insgesamt und unabhängig seiner Devices betrifft.
Für die einzelnen Devices bedarf es ein globales Event, damit man es von einem STATE Event unterscheiden kann.
Ergo vielleicht während der FHEM Initialisierungsphase:
global:INITIALIZED
global:<TYPE>:INITIALIZED <device>
global:<TYPE>:INITIALIZED
Während der FHEM Laufzeit:
global:<TYPE>:MODIFIED <device>
global:<TYPE>:.+
Im Grunde genommen würde ich damit annehmen, dass man allen Events, die global bereits definiert hat, ein <TYPE>: voranstellen kann. Neu im Scope eines Moduls ist dann einzig, dass es neben "INITIALIZED" noch "INITIALIZED <device>" gibt. Das ist im Scope eines Moduls logisch und führt auch zu keinen bestehenden Konflikten.
Um das Format sicherzustellen, können wir eine Wrapper-Funktion DoModuleTrigger() bereitstellen:
sub DoModuleTrigger($$@) {
my ($type, $newState, $noreplace) = @_;
$noreplace = 1 unless(defined($noreplace));
return DoTrigger("global", $type.":".$newState, $noreplace);
}
Das entspräche wohl auch in etwa dem, was André sich vorgestellt hat.
rudi voraschlag ist immer noch am einheitlichsten und verträgt sich glaube ich am besten mit NOTIFYDEV. die wenn das event zur laufzeit INITIALIZED nicht ausreicht würde ich trotzdem das gleiche format wie wie beim INITALIZED event verwenden.
hab gerade mal grob über alle module geschaut. direkt aufgefallen sind mir nur CUL_HM, pilight_ctrl, HMinfo, weekprofile und DOIFtools die probleme bekommen. es sollte aber auf jeden fall vorher angekündigt werden.
Siehe aktualisierten Post vorher:
Zitat von: Loredo am 22 April 2017, 15:41:05
Im Grunde genommen würde ich damit annehmen, dass man allen Events, die global bereits definiert hat, ein <TYPE>: voranstellen kann. Neu im Scope eines Moduls ist dann einzig, dass es neben "INITIALIZED" noch "INITIALIZED <device>" gibt. Das ist im Scope eines Moduls logisch und führt auch zu keinen bestehenden Konflikten.
Um das Format sicherzustellen, können wir eine Wrapper-Funktion DoModuleTrigger() bereitstellen:
sub DoModuleTrigger($$@) {
my ($type, $newState, $noreplace) = @_;
$noreplace = 1 unless(defined($noreplace));
return DoTrigger("global", $type.":".$newState, $noreplace);
}
Das entspräche wohl auch in etwa dem, was André sich vorgestellt hat.
das klingt gut. so rum gibt es keine konflikte und es ist in sich konsistent und einheitlich.
Zitat von: justme1968 am 22 April 2017, 16:03:40
das klingt gut. so rum gibt es keine konflikte und es ist in sich konsistent und einheitlich.
Ich habe es jetzt einmal testweise so umgestellt; damit kommt es erstmal zu keinen Konflikten mehr.
Auch habe ich nun wohl auch eine Lösung dafür gefunden zunächst alle Devices zu initialisieren (Event pro Device: ^<TYPE>:INITIALIZED <device>$) , bevor ich das Modul-globale Event sende, dass das Modul fertig initialisiert ist.
Damit kann man sicher sagen, dass alle Devices auf jeden Fall auch initialisiert sind, wenn ^<TYPE>:INITIALIZED$ geschickt wird.
Was ich den ganzen Vormittag/halben Nachmittag nicht geschafft habe ist, dass das bei einem rereadcfg auch genauso klappt. Das Problem ist dabei, dass alle Devices natürlich das REREADCFG Event erhalten. Beim ^INITIALIZED$ kriege ich das gefiltert, so dass nur das allererste Device die Modulinitialisierung übernimmt. Aber bei REREADCFG gelingt mir das einfach nicht, so dass jedes Device nochmals alle anderen Devices des gleichen TYPE initialisieren. Das ist natürlich mehr als unschön :-/
Hat da jemand Lust auch drüber zu grübeln?
Zitat von: justme1968 am 22 April 2017, 13:53:37
<device>:INITIALIZED
ist nicht gut da man dann den device namen kennen muss
Na und? Es geht doch gerade um den Fall, dass man auf die Initialisierungsphase eines bestimmten Device wartet.
Zitat von: Loredo am 22 April 2017, 15:32:19
Weil man es sonst nicht von einem STATE Event unterscheiden kann.
Was ist denn ein "STATE Event"?
Meiner Meinung nach sollte man verbieten, dass ein Modul ein global-Event feuert. ...am besten im fhem.pl abfangen.
Wenn unbedingt jemand eine Funktion braucht, die ihm sagt, dass alle Devices eines Moduls initialisiert sind, dann kann er sich das ja selbst bauen. (Wozu eigentlich???) Das geht, indem man nach global:INITIALIZED sich alle Devices zum Modul holt und sie dann nach und nach "abhakt", wenn alle INITIALIZED-Events da sind.
Am besten macht man das Device-INITIALIZED-Event gleich zu einem ordentlichen Reading, dann geht das ganze noch einfacher.
Gruß,
Thorsten
mal unabhängig vom wozu braucht man das: das selber bauen geht nicht da die liste der devices nach dem INITIALIZED nicht unbedingt vollständig ist falls ein master device noch child devices per autocreate hinzufügt.
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 16:17:54
Meiner Meinung nach sollte man verbieten, dass ein Modul ein global-Event feuert. ...am besten im fhem.pl abfangen.
Nicht sonderlich liberal... die Frage ist ja, weshalb du das unterbinden willst? Was bringt es dir denn?
Module mit X_Notify() Funktion sollen ja bestmöglich ihren Scope per NOTIFYDEV einschränken. Ein Modul holt sich die Events also nur, wenn es sie auch braucht.
Man kann darüber nachdenken, ob man die Modul-globalen Events noch über NOTIFYDEV filterbar macht, indem man z.B. "global:<TYPE>:" dort mit berücksichtigt (wäre ein Sonderfall bzw. eine Abweichung vom reinen devspec2array() ).
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 16:17:54
(Wozu eigentlich???) Das geht, indem man nach global:INITIALIZED sich alle Devices zum Modul holt und sie dann nach und nach "abhakt", wenn alle INITIALIZED-Events da sind.
Das funktioniert nur, wenn das andere Modul keine seiner Initialisierungsfunktionen von global:INITIALIZED abhängig macht. Sobald beide Module X_Notify() verwenden und darin für ihre Funktion auf global:INITIALIZED setzen, wird es schwieriger. Man kann in einigen Fällen NotifyOrderPrefix als Krücke verwenden, aber alle Fälle deckt das auch nicht ab. Ändert sich ein Modul, kann es dann sehr leicht davon abhängige andere Module brechen. Um davon unabhängig zu sein, braucht es die beschriebenen globalen Events, vor allem für die Initialisierungsphase.
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 16:17:54
Was ist denn ein "STATE Event"?
Ich habe das bisher so verstanden:
Devices verschicken normalerweise Events in der Form "reading: value". Allerdings gibt es eine Ausnahme, wenn sich das Value für das Internal STATE ändert.
Früher wurde dabei das Präfix "reading:" weggelassen, weshalb dann nur "value" geschickt wurde. Man kann zwar auch inzwischen ein Event in der Form "state: value" erhalten, das ist aber nicht abwärtskompatibel. Ein Event auf Device Ebene ala DoTrigger($name, "INITIALIZED",1) lässt sich also nicht von einem Event unterscheiden, bei dem das Reading state zufällig auch den Wert "INITIALIZED" hat.
das event ohne den reading namen ist für state. nicht STATE. der rest bzw. die probleme damit stimmen aber.
nur per longpoll gibt es tatsächlich ein event für STATE. da kommt man aber per notify nicht dran.
Zitat von: justme1968 am 22 April 2017, 16:43:04
das event ohne den reading namen ist für state. nicht STATE. der rest bzw. die probleme damit stimmen aber.
nur per longpoll gibt es tatsächlich ein event für STATE. da kommt man aber per notify nicht dran.
Mist, die Chance war 50/50 und ich hatte mich nochmal umentschieden ;D
Danke für die Richtigstellung, ist immer gut die Details zu kennen und zu verstehen.
Zitat von: justme1968 am 22 April 2017, 16:25:59
mal unabhängig vom wozu braucht man das: das selber bauen geht nicht da die liste der devices nach dem INITIALIZED nicht unbedingt vollständig ist falls ein master device noch child devices per autocreate hinzufügt.
Mir fällt jetzt irgendwie kein richtiges Szenario ein, wo man dann auch nich wissen muss, dass alle Devices zu einem Modul angelegt sind und nicht doch noch später sowieso weitere Devices dazukommen können. Ich denke mal, in so einem Fall müsste man halt auf das "Erscheinen" jedes Device reagieren.
...oder eben das Master-Device darf sein INIZIALIZED nicht triggern bevor es nicht alle Kinder angelegt hat.
Zitat von: Loredo am 22 April 2017, 16:37:54
Nicht sonderlich liberal... die Frage ist ja, weshalb du das unterbinden willst? Was bringt es dir denn?
Ok, das war vielleicht etwas hart formuliert. Ich fände es halt schon irgendwie seltsam, wenn jemand ein Modul schreibt, welches Events generiert, die von "meinem" Modul auszugehen scheinen. ...und für mich ist "global" halt auch jemandes Modul.
Ich verstehe halt immer noch nicht, warum das unbedingt ein globales Event sein muss.
ZitatDas funktioniert nur, wenn das andere Modul keine seiner Initialisierungsfunktionen von global:INITIALIZED abhängig macht. Sobald beide Module X_Notify() verwenden und darin für ihre Funktion auf global:INITIALIZED setzen, wird es schwieriger...
Das verstehe ich jetzt nicht. Kannst Du dafür mal ein Beispiel zeigen?
ZitatIch habe das bisher so verstanden:
Devices verschicken normalerweise Events in der Form "reading: value". Allerdings gibt es eine Ausnahme, wenn sich das Value für das Internal STATE ändert.
Früher wurde dabei das Präfix "reading:" weggelassen, weshalb dann nur "value" geschickt wurde. Man kann zwar auch inzwischen ein Event in der Form "state: value" erhalten, das ist aber nicht abwärtskompatibel. Ein Event auf Device Ebene ala DoTrigger($name, "INITIALIZED",1) lässt sich also nicht von einem Event unterscheiden, bei dem das Reading state zufällig auch den Wert "INITIALIZED" hat.
Ok, mal davon ausgehend dass Du tatsächlich state und nicht STATE meinst: Unter Anderem deshalb meine ich ja, dass man daraus ein richtiges Reading machen sollte. Dann gibt's das Problem nicht mehr.
Gruß,
Thorsten
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 19:31:50
Mir fällt jetzt irgendwie kein richtiges Szenario ein, wo man dann auch nich wissen muss, dass alle Devices zu einem Modul angelegt sind und nicht doch noch später sowieso weitere Devices dazukommen können. Ich denke mal, in so einem Fall müsste man halt auf das "Erscheinen" jedes Device reagieren.
...oder eben das Master-Device darf sein INIZIALIZED nicht triggern bevor es nicht alle Kinder angelegt hat.
Man muss unterscheiden zwischen dem FHEM Startvorgang und den Änderungen während der Laufzeit, die dann entweder durch User-Interaktion oder durch Modul-interne Vorgänge stattfinden. Ob es sinnvoll ist eine Reihenfolge bei den Modul-globalen INITIALIZED Meldungen für das Modul selbst und den Devices einzuhalten, ist dem Modulautor zu überlassen. In der Regel dürfte es aber Sinn machen zunächst über die einzelnen Devices zu informieren und abschließend über das Modul.
Für Änderungen während der Laufzeit gibt es ja die definierten Events wie "MODIFIED", welche man dann natürlich auch entsprechend im Kontext des Moduls verwenden kann, um nach der Initialisierungsphase zu informieren. Auch das ist Modul-spezifisch. RESIDENTS macht das nun derzeit so:
# finish module initialization
if ( !$modules{$TYPE}{READY} && !$modules{$TYPE}{INIT} ) {
$modules{$TYPE}{INIT} = 1;
foreach ( devspec2array("TYPE=$TYPE") ) {
$defs{$_}{'.READY'} = 0;
RESIDENTStk_findResidentSlaves( $defs{$_} )
if ( $TYPE eq "RESIDENTS" );
RESIDENTStk_findDummySlaves( $defs{$_} )
if ( $TYPE ne "RESIDENTS" );
}
Log 5, "$TYPE: module initialization completed";
delete $modules{$TYPE}{INIT};
$modules{$TYPE}{READY} = 1;
RESIDENTStk_DoModuleTrigger( $TYPE, "INITIALIZED" );
}
# finish device initialization
elsif ( !$hash->{'.READY'} ) {
Log3 $name, 5, "$TYPE $name: device initialization completed";
$hash->{NOTIFYDEV} = $NOTIFYDEV;
$hash->{'.READY'} = 1;
RESIDENTStk_DoModuleTrigger( $TYPE, "INITIALIZED $name" );
}
# device setup changed during runtime
elsif ( $hash->{NOTIFYDEV} ne $NOTIFYDEV ) {
$hash->{NOTIFYDEV} = $NOTIFYDEV;
Log3 $name, 5, "$TYPE $name: device re-configuration completed";
RESIDENTStk_DoModuleTrigger( $TYPE, "MODIFIED $name" );
}
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 19:31:50
Ok, das war vielleicht etwas hart formuliert. Ich fände es halt schon irgendwie seltsam, wenn jemand ein Modul schreibt, welches Events generiert, die von "meinem" Modul auszugehen scheinen. ...und für mich ist "global" halt auch jemandes Modul.
Deshalb unterhalten wir uns hier ja darüber.
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 19:31:50
Ich verstehe halt immer noch nicht, warum das unbedingt ein globales Event sein muss.
[...]
Das verstehe ich jetzt nicht. Kannst Du dafür mal ein Beispiel zeigen?
Ich kann dir hier nicht das gesamte Event Handling von FHEM erläutern. Das beste Beispiel ist der ursprüngliche Grund dieses Threads, nämlich Dans HOMEMODE Modul im Zusammenspiel mit RESIDENTS. Dazu musst du nur die Nachrichten von Anfang an lesen.
Zitat von: Thorsten Pferdekaemper am 22 April 2017, 19:31:50
Ok, mal davon ausgehend dass Du tatsächlich state und nicht STATE meinst: Unter Anderem deshalb meine ich ja, dass man daraus ein richtiges Reading machen sollte. Dann gibt's das Problem nicht mehr.
Ein Reading ist mehr als nur ein Event und es kann nur auf Device-Ebene stattfinden. Wir reden hier von eine Abstraktionsebene höher, der allgemeinen Modulebene, die zunächst erst einmal gerätelos ist. Deshalb sind wir dann auch automatisch bei Events des Pseudo-Devices "global", da nur dafür ein gesondertes Event Handling in FHEM existiert. Es ist schlicht der Architektur von FHEM geschuldet, dass Events IMMER an einem Device hängen müssen, FHEM selbst und alle Module jedoch zunächst einmal gerätelos sind.
Deshalb gibt es auch zwei Funktionen, die bei der Initialisierung eines Moduls eine Rolle spielen: X_Initialize() initialisiert das Modul ansich unter %modules, X_Define() das jeweilige Device unter %defs.
Zitat von: Loredo am 23 April 2017, 11:46:05
Ich kann dir hier nicht das gesamte Event Handling von FHEM erläutern.
Wozu auch?
ZitatDas beste Beispiel ist der ursprüngliche Grund dieses Threads, nämlich Dans HOMEMODE Modul im Zusammenspiel mit RESIDENTS. Dazu musst du nur die Nachrichten von Anfang an lesen.
Das habe ich getan. ...und jetzt nochmal. Es sieht doch so aus, dass das HOMEMODE-Device "sein" RESIDENTS-Device kennt. D.h. es interessiert eigentlich nur, ob dieses Device schon fertig ist. Warum muss man wissen, ob alle RESIDENTS fertig sind?
Zitat
Ein Reading ist mehr als nur ein Event
...und genau deshalb fände ich hier ein Reading angebracht.
Zitat
Wir reden hier von eine Abstraktionsebene höher, der allgemeinen Modulebene, die zunächst erst einmal gerätelos ist. Deshalb sind wir dann auch automatisch bei Events des Pseudo-Devices "global", da nur dafür ein gesondertes Event Handling in FHEM existiert. Es ist schlicht der Architektur von FHEM geschuldet, dass Events IMMER an einem Device hängen müssen, FHEM selbst und alle Module jedoch zunächst einmal gerätelos sind.
Deshalb gibt es auch zwei Funktionen, die bei der Initialisierung eines Moduls eine Rolle spielen: X_Initialize() initialisiert das Modul ansich unter %modules, X_Define() das jeweilige Device unter %defs.
Das ist mir alles klar. Mir ist nur nicht klar, warum man das auf Modulebene braucht.
Gruß,
Thorsten
Da ich es nicht geschafft habe den rereadcfg Fall rein über die bestehenden Events richtig zu handhaben, habe ich jetzt einen Patch geschrieben, der FHEM um eine neue ModulFn InitDevFn erweitert.Beiliegender Patch beinhaltet die zwei neuen Funktionen DoModuleTrigger() und DoInitDev() sowie die Anpassungen, um InitDevFn als Modul Funktion registrieren zu können.
Das Modul-globale Event Handling ist darin so gekapselt, dass man als Modulautor nur die InitDevFn bereitstellen muss. Dafür werden die folgenden Variablen verwendet, um den Initialisierungsstatus zu speichern:
$modules{$m}{READY}
$modules{$m}{INIT}
$defs{$d}{READY}
$defs{$d}{MOD_INIT}
Es ist sichergestellt, dass man über DoModuleTrigger() nur Modul-eigene Events auslösen kann. Die Events TYPE:INITIALIZED, TYPE:INITIALIZING, TYPE:MODIFIED und TYPE:DELETED kann man nicht übersteuern, sie werden vollständig von DoModuleTrigger verwaltet.
Beispiel wie eine InitDevFn für RESIDENTS/ROOMMATE/GUEST aussehen würde:
sub RESIDENTStk_InitializeDev($) {
my ($hash) = @_;
$hash = $defs{$hash} unless ( ref($hash) );
my $NOTIFYDEV = "global";
if ( $hash->{TYPE} eq "RESIDENTS" ) {
$NOTIFYDEV .= "," . RESIDENTStk_findResidentSlaves($hash);
}
else {
$NOTIFYDEV .= "," . RESIDENTStk_findDummySlaves($hash);
}
return 0
if ( defined( $hash->{NOTIFYDEV} ) && $hash->{NOTIFYDEV} eq $NOTIFYDEV );
$hash->{NOTIFYDEV} = $NOTIFYDEV;
return undef;
}
Entsprechende globale Events werden dann für das Modul gehandhabt.
Folgende Events werden während des Startvorgangs _nach_ global:INITIALIZED erzeugt:
1. je Device => global:TYPE:INITIALIZED <device>
2. erst wenn alle Devices initialisiert wurden => global:TYPE:INITIALIZED
Je nach Rückgabe der InitDevFn wird ermittelt, ob und wie ein Event ausgelöst wird. Für verzögerte Geräte muss man nur einen nicht leeren Returnwert liefern. Eine Ausnahme bildet der Returnwert 0: Er bedeutet, dass keine strukturellen Änderungen am Device vorgenommen wurden und deshalb kein Event ausgelöst werden muss. Undef oder "" wird als erfolgreiche Initialisierung gewertet.
Während der Laufzeit kann der Modulautor die Wrapper-Funktion DoInitDev([$name|@array]) so oft ausführen, wie er möchte. Darüber wird indirekt seine InitDevFn aufgerufen und die Modul-globalen Events werden dann entsprechend gesteuert. Außerdem ist auch die Nutzung von DoModuleTrigger() ähnlich wie DoTrigger() möglich. Man kann darüber auch manuell die Events auslösen, die sonst über DoInitDev() gesteuert werden.
------
TL;DR
Im Bezug auf die Problematik, dass einige Module die globalen Events nur unzureichend filtern, habe ich alle betroffenen Modulautoren per PM angeschrieben:
HMInfo (martinp876)
DOIF (Damian)
weekprofile, pilight_ctrl (Risiko)
DOIFtools (Ellert)
DUOFERNSTICK (Telekatz)
Gruß
Julian
Zitat von: Thorsten Pferdekaemper am 23 April 2017, 12:48:24
Das habe ich getan. ...und jetzt nochmal. Es sieht doch so aus, dass das HOMEMODE-Device "sein" RESIDENTS-Device kennt. D.h. es interessiert eigentlich nur, ob dieses Device schon fertig ist. Warum muss man wissen, ob alle RESIDENTS fertig sind?
Das fragst du bitte Dan.
ZitatDa ich es nicht geschafft habe den rereadcfg Fall rein über die bestehenden Events richtig zu handhaben, habe ich jetzt einen Patch geschrieben
Wenn ich diesen Patch einspielen soll, dann muss ich erst verstehen, warum es notwendig ist, und ja, ich habe deine Erklaerung hier (https://forum.fhem.de/index.php/topic,70882.msg624669.html#msg624669) gelesen. Kannst du bitte erlaeutern, was genau nicht moeglich ist?
Zitat von: Loredo am 24 April 2017, 00:46:45
Das fragst du bitte Dan.
Das kann ich nicht beantworten, das ist nicht auf "meinem Mist" gewachsen.
Mir reicht es zu wissen wann genau das eine überwachte RESIDENTS Device, dessen Namen ich auch habe, initialisiert ist.
Bisher klappt das auch ohne die neuen Events von Loredo dank NotifyOrderPrefix.
Gab es hier schon eine grundlegende Entscheidung zum Event-Handling bezüglich Modul/Device Initialisierung?
Gruß
Dan
Zitat von: Thorsten Pferdekaemper am 23 April 2017, 12:48:24
Warum muss man wissen, ob alle RESIDENTS fertig sind?
Damit festgestellt werden kann, wenn sich zur Laufzeit etwas geändert hat (RESIDENTS hat neue Bewohner aufgenommen oder entfernt) und Dan sein set updateInternalsForce in Rente schicken könnte. Während des Bootups ist es aktuell ein Nebenprodukt, es wird sicherlich jemand findiges auf Ideen kommen das sinnvoll zu verwenden, wenn die Funktion erstmal da ist.
Zitat von: DeeSPe am 24 April 2017, 11:05:14
Das kann ich nicht beantworten, das ist nicht auf "meinem Mist" gewachsen.
Nicht ganz, ich habe deine Anforderungen ja sehr wohl ernst genommen:
https://forum.fhem.de/index.php/topic,70882.msg624225.html#msg624225 (https://forum.fhem.de/index.php/topic,70882.msg624225.html#msg624225)
Zitat von: DeeSPe am 24 April 2017, 11:05:14
Mir reicht es zu wissen wann genau das eine überwachte RESIDENTS Device, dessen Namen ich auch habe, initialisiert ist.
Bisher klappt das auch ohne die neuen Events von Loredo dank NotifyOrderPrefix.
NotifyOrderPrefix verwende ich nun nicht mehr, da die Module ihre eigenen Events für die Fertigstellung generieren können.
Zitat von: DeeSPe am 24 April 2017, 11:05:14
Gab es hier schon eine grundlegende Entscheidung zum Event-Handling bezüglich Modul/Device Initialisierung?
IMHO sind wir dabei das auszuloten und ich habe dafür einen POC in meine Module eingebaut sowie einen generellen Patch für fhem.pl bereitgestellt, damit es keine Eigenbrödlerlösung bleiben muss und alle etwas davon haben können.
Zitat von: rudolfkoenig am 24 April 2017, 10:55:36
Wenn ich diesen Patch einspielen soll, dann muss ich erst verstehen, warum es notwendig ist, und ja, ich habe deine Erklaerung hier (https://forum.fhem.de/index.php/topic,70882.msg624669.html#msg624669) gelesen. Kannst du bitte erlaeutern, was genau nicht moeglich ist?
Nachdem ich die eigentlich für FHEM global gedachte Implementierung nun nochmals (fast) 1-zu-1 in meine Module eingebunden habe, kann ich es auf diese Dinge eingrenzen:
1. Beim triggern auf global:INITIALIZED werden die Devices unnötig mehrfach initialisiert bzw. zumindest die Funktion mehrfach aufgerufen, da das Event bei jedem einzelnen Gerät auch dann noch eintrifft, wenn es bereits über das allerste Gerät aus fhem.cfg initialisiert wurde.
2. Auf DELETED Events können Module nicht reagieren, da für das gelöschte Device die Information nicht mehr zu Verfügung steht, welchem Modul das Gerät einmal gehört hat.
3. Es ist nicht möglich ein Modul-globales Event zu senden, nachdem das letzte Devices eines Moduls gelöscht wurde.
4. Die "Hoheit" über die globalen Events bleibt bei fhem.pl (davon ausgehend, dass Modulautoren DoTrigger() nicht verwenden, sondern DoModuleTrigger()).
Das mögen jetzt nicht mehr die dringendsten Gründe sein. Ich meine aber, dass die Bereitstellung dieser Funktionalität als InitDevFn für alle Modulautoren eine sinnvolle Ergänzung wäre. Natürlich kann man das noch feinschleifen, dafür bin ich aber auf Mitarbeit angewiesen.
Gruß
Julian
Zitat von: Loredo am 24 April 2017, 17:19:25
Ich meine aber, dass die Bereitstellung dieser Funktionalität als InitDevFn für alle Modulautoren eine sinnvolle Ergänzung wäre.
Ich würde das jetzt nicht verallgemeinern. Mag sein, dass es für das eine oder andere Modul sinnvoll ist, für meine Module kann ich da jetzt keinen Usecase ausmachen.
Ich spreche vom Angebot, nicht der Nachfrage.
Aber ich bin die Diskussion auch schon wieder leid... :-X
Zitat von: Loredo am 24 April 2017, 17:19:25
Nicht ganz, ich habe deine Anforderungen ja sehr wohl ernst genommen:
https://forum.fhem.de/index.php/topic,70882.msg624225.html#msg624225 (https://forum.fhem.de/index.php/topic,70882.msg624225.html#msg624225)
Vielen Dank für Deinen Einsatz.
Leider hast Du mich wohl missverstanden.
Ich habe niemals eine Anforderung gestellt:
Zitat von: DeeSPe am 21 April 2017, 21:05:12
Genau das ist der Punkt warum es in meinem Modul "set <name> updateInternalsForce" gibt. Wenn sich ein überwachter TYPE erweitert/verringert dann muss eben genau das ausgeführt werden damit die Device aktualisiert werden ohne Neustart.
Das war lediglich eine Feststellung dass ich generell dazu keine Möglichkeit gefunden habe. Es ging mir dabei garnicht primär um RESIDENTS, denn die ändern sich ja i.d.R. nicht so oft. Mein Modul überwacht noch ein Vielzahl weiterer Geräte (z.B. Kontakt- und Bewegungssensoren), bei denen durchaus mal der ein oder andere dazukommt oder wegfällt.
Deswegen ging es mir um eine evtl. allgemein gültige Lösung. Vielen Dank für Deinen Vorschlag dazu.
Mein ursprüngliches Problem war durch Ändern von NotifyOrderPrefix in meinem Modul bereits gelöst, zumindest habe ich bisher nichts Nachteiliges feststellen können.
Für die allgemein gültige Lösung bin ich weiterhin offen und finde Dein PoC gut! Ich kann aber die Tragweite nicht beurteilen und ob das für jeden Entwickler sinnvoll zu integrieren geht.
Gruß
Dan
P.S. Die endgültige Lösung sollte dann auch "in Stein gemeisselt" werden (commandref + DeveloperGuide).
Zitat1. Beim triggern auf global:INITIALIZED werden die Devices unnötig mehrfach initialisiert bzw. zumindest die Funktion mehrfach aufgerufen, da das Event bei jedem einzelnen Gerät auch dann noch eintrifft, wenn es bereits über das allerste Gerät aus fhem.cfg initialisiert wurde.
Meiner Ansicht nach kann man das auch ohne Patch:
Variante a) ohne Notify
Im MODUL_Initialize() folgendes aufrufen:
InternalTimer(1, "MyModuleFinalInitializer", undef);
Variante b) mit Notify auf global:INITIALIZED
Im DefineFn folgendes einbauen:
if(!$modules{MODULNAME}{ldata}{notifyset}) {
$modules{MODULNAME}{ldata}{notifyset} = 1;
$hash->{NOTIFYDEV} = "global";
} else {
$hash->{NOTIFYDEV} = "__NO_DEVICE__";
}
Im notifyFn kann man dann entweder $modules{MODULNAME}{NotifyFn} entfernen oder NOTIFYDEV aendern oder alles lassen, wie es ist.
Damit rereadcfg funktioniert, bzw. der Benutzer ohne FHEM Neustart beliebig Instanzen entfernen kann, muss man im UndefFn dafuer sorgen, dass NOTIFYDEV an der naechsten Instanz weitergegeben wird, bzw. beim Entfernen der Letzten notifyset entfernt wird.
Zitat2. Auf DELETED Events können Module nicht reagieren, da für das gelöschte Device die Information nicht mehr zu Verfügung steht, welchem Modul das Gerät einmal gehört hat.
Das ist leider unpraezise formuliert. Fuer das eigene Modul gibt es UndefFn, andere Module muessen das Modul der anderen Instanz merken, wenn das beim Entfernen dort eine Rolle spielt.
Zitat3. Es ist nicht möglich ein Modul-globales Event zu senden, nachdem das letzte Devices eines Moduls gelöscht wurde.
Im UndefFn kann man pruefen, ob es noch andere Modul-Instanzen gibt, und wenn nicht, ein Event per DoTrigger vor dem return senden. Ich habe aber Schwierigkeiten vorzustellen, wozu das gut sein soll.
Meine Vorschlaege sind teilweise nicht elegant, ich bin aber noch auf dem Standpunkt, dass man fuer seltene Sonderfaelle keine Abkuerzungen einbauen muss.