FHEM Forum

FHEM - Entwicklung => FHEM Development => Thema gestartet von: Loredo am 12 Januar 2017, 21:49:10

Titel: Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 12 Januar 2017, 21:49:10
Hi,


gibt es eine Möglichkeit, dass man den Loop-Schutz umgehen/überstimmen kann?
Bei der Entwicklung von 98_powerMap werden in X_Notify() die Events der unterschiedlichen Devices ausgewertet, um dann wiederum 2 weitere Readings im selben Device zu aktualisieren, welches die Eventkette ausgelöst hat. Die beiden Readings sind in X_Notify() entsprechend abgefangen, so dass kein Loop entstehen kann.


Allerdings wird das Event nach Aufruf von readingsEndUpdate() nicht so ganz richtig erzeugt. Die aktualisierten Readings tauchen zwar im Eventmonitor auf, aber die Ansichten werden nicht über Longpoll aktualisiert. Außerdem werden dadurch die Events auch nicht per FileLog geloggt, was ausgerechnet bei diesen zwei Readings eigentlich Sinn und Zweck der Aktion sein soll.


Wäre sehr dankbar, wenn das jemand näher erläutern und helfen könnte, wie man das gelöst bekommt.




Gruß
Julian
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: gandy am 12 Januar 2017, 22:15:54
Hi, hast du dir mal dewpoint oder statistics angesehen, die machen evtl etwas ähnliches.

Grüße,
Andy.
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Thorsten Pferdekaemper am 12 Januar 2017, 22:25:36
Hi,
die übliche InternalTimer-Technik hilft da nicht?
Gruß,
  Thorsten
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 13 Januar 2017, 12:42:28
Sowas mit InternalTimer zu lösen würde mir irgendwie widerstreben. Möchte ich eigentlich nur im Notfall so tun.


Mir ist aber auch aufgefallen, dass die Demo Umgebung von fhem.cfg.demo auch Probleme mit Updates hat. Wenn ich dort z.B. im Raum "Light" Living Room ein und aus schalten, dann wird der pct Schieberegler nur beim einschalten aktualisiert, jedoch nicht beim ausschalten. Vielleicht besteht also auch ein Zusammenhang mit den jüngsten Änderungen für Websockets.
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Thorsten Pferdekaemper am 13 Januar 2017, 18:19:41
Zitat von: Loredo am 13 Januar 2017, 12:42:28Sowas mit InternalTimer zu lösen würde mir irgendwie widerstreben. Möchte ich eigentlich nur im Notfall so tun.
Was ist daran böse? FHEM erledigt das dann einfach sozusagen in der nächsten Runde. Ich denke auch, dass es für das Antwortverhalten des Systems insgesamt sogar besser ist.
Gruß,
   Thorsten
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: rudolfkoenig am 13 Januar 2017, 18:33:56
ZitatBei der Entwicklung von 98_powerMap werden in X_Notify() die Events der unterschiedlichen Devices ausgewertet, um dann wiederum 2 weitere Readings im selben Device zu aktualisieren, welches die Eventkette ausgelöst hat.

average/dewpoint machen was aehnliches, ohne das Problem zu haben, indem sie nicht die readings*Update Funktionen aufrufen, sondern die Readings direkt anlegen/modifizieren. Hat den Nachteil, dass die so erstellten Readings nicht fuer die event-* Attribute oder fuer stateFormat zur Verfuegung stehen.

ZitatVielleicht besteht also auch ein Zusammenhang mit den jüngsten Änderungen für Websockets.
Auf welche Beweise stuetzt sich diese Hypothese?
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 13 Januar 2017, 20:19:11
Zitat von: rudolfkoenig am 13 Januar 2017, 18:33:56
Hat den Nachteil, dass die so erstellten Readings nicht fuer die event-* Attribute oder fuer stateFormat zur Verfuegung stehen.


Eben drum.


Zitat von: rudolfkoenig am 13 Januar 2017, 18:33:56
Auf welche Beweise stuetzt sich diese Hypothese?


Das Wort "Vielleicht" sollte die Indikation geben, dass ich "Beweise" geliefert hätte, lägen mir solche vor oder hätte ich sonst irgendwelche Anstrengungen in diese Richtung unternommen.
Ich habe die Submissions dazu nicht durchgelesen, aber manchmal brauchen Menschen ja nur ein bestimmtes Stichwort, damit es ihnen "wie Schuppen von den Augen" fällt. Offenbar ist das hier nicht der Fall, was auch ok ist.
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 13 Januar 2017, 20:20:48
Zitat von: Thorsten Pferdekaemper am 13 Januar 2017, 18:19:41
Ich denke auch, dass es für das Antwortverhalten des Systems insgesamt sogar besser ist.


Bei einem 286er ohne Co-Prozessor hast du sicherlich Recht  ;)
Ansonsten glaube ich nicht, dass das merklich ins Gewicht fallen würde (und auch nur unwesentlich messbar).
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Thorsten Pferdekaemper am 13 Januar 2017, 20:49:49
Zitat von: Loredo am 13 Januar 2017, 20:20:48
Bei einem 286er ohne Co-Prozessor hast du sicherlich Recht  ;)
Ansonsten glaube ich nicht, dass das merklich ins Gewicht fallen würde (und auch nur unwesentlich messbar).
Kommt das nicht darauf an, welche Notifies wiederum an den abgeleiteten Readings hängen? Je nachdem wie viele das sind und was die treiben, kann das schon einen Unterschied machen. ...oder?
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 13 Januar 2017, 21:05:29
Sicherlich messbar, aber bis das merkbar so wäre (im vierstelligen msec Bereich) müsste IMHO schon einiges passieren und es sich um eine riesige FHEM Installation handeln...


Man vergisst immer, dass auch die kleinen Prozessoren heutzutage so schnell sind, dass man die Loops nicht im menschen Gehirn gedanklich durchgehen kann. Da trügt das Gefühl oft, dass das so extrem viel wäre, weil man sich in seinen komplexen Quellcode verdenkt.


Aber da darf man gerne unterschiedlicher Auffassung drüber sein.
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 09:51:34
Hallo Rudi,


ich bin nicht sicher, ob ich das essentielle aus den beiden genannten Modulen richtig herauslese.


Ich habe jetzt testhalber die Readings selbst direkt geschrieben. Die Notification Loop habe ich einfach entsprechend ergänzt, aber das scheint keinen Effekt zu haben.




                $dev_hash->{READINGS}{$rname_p}{TIME} = $tn;
                $dev_hash->{READINGS}{$rname_p}{VAL} = $power;
                $dev_hash->{CHANGED}[$max++] = "$rname_p: $power";



Was fehlt denn da noch? Ich kann da im Grundsatz keinen Unterschied zu den Modulen dewpoint oder average erkennen...
Kann es sein, dass die Notification Loop noch mit der alten Anzahl an Änderungen läuft und wenn ja, wie müsste ich die wieder neu anstarten?




Gruß
Julian

Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 14 Januar 2017, 10:09:26
Der Grund, warum das bei average so funktioniert, liegt in der Reihenfolge in der Events verarbeitet werden.

Das Modul average hat in der Initialize()-Funktion ein geändertes NotifyOrderPrefix gesetzt, so dass es bei der Verarbeitung von Events IMMER zuerst aufgerufen wird:

$hash->{NotifyOrderPrefix} = "10-"

Dadurch kann es für die eventerzeugenden Geräte $hash->{CHANGED} mit zusätzlichen Events zu erweitern. Das Modul dewpoint nutzt das gleiche Schema. Das ganze ist im Wiki zu X_Notify() beschrieben: https://wiki.fhem.de/wiki/DevelopmentModuleIntro#X_Notify (Abschnitt: Reihenfolge für den Aufruf der Notify-Funktion beeinflussen)

Gruß
Markus
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Thorsten Pferdekaemper am 14 Januar 2017, 10:12:39
Zitat von: Loredo am 13 Januar 2017, 21:05:29Sicherlich messbar, aber bis das merkbar so wäre (im vierstelligen msec Bereich) müsste IMHO schon einiges passieren und es sich um eine riesige FHEM Installation handeln...
Naja, ich weiß ja nicht, wie schnell Du was merkst, aber wenn ich auf eine Taste drücke, und das Licht geht erst 100ms später an, dann behaupte ich, da schon was zu merken. Für mich sind eigentlich nur Verzögerungen im zweistellugen ms-Bereich akzeptabel.

ZitatMan vergisst immer, dass auch die kleinen Prozessoren heutzutage so schnell sind, dass man die Loops nicht im menschen Gehirn gedanklich durchgehen kann. Da trügt das Gefühl oft, dass das so extrem viel wäre, weil man sich in seinen komplexen Quellcode verdenkt.
So ein bisschen Erfahrung habe ich schon in dem Geschäft. Ich weiß auch, dass es oft der einfach erscheinende Code ist, der Performance-Probleme bereitet.
Aber ich muss zugeben, dass mein Einwand eher prinzipieller Natur war und ich den konkreten Fall nicht weiter untersucht habe.

Gruß,
   Thorsten
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 10:17:17
Okay verstehe. Dann bleibt mir für mein Modul aber wohl nur der Weg über den InternalTimer, da die Reihenfolge hier anders herum ist: Das Fremdmodul löst eine Statusänderung aus und diese dient als Trigger dafür den Stromverbrauchswert neu zu berechnen. Da hilft es leider nicht, wenn powerMap dann in der Priorität höher steht, denn es wird das erste Mal dadurch aufgerufen, dass das eben die Eventverarbeitung beim Fremdmodul gestartet ist. Gleichzeitig soll genau dieser Loop erweitert werden. DoTrigger() zählt aber in seiner eigenen Loop nur zu Beginn die Anzahl der Array Elemente und ignoriert daher Änderungen, die während der Loop Verarbeitung gemacht werden. Habe noch nicht ausprobiert, ob man DoTrigger() dahingehend erweitern kann, aber ich vermute das wäre auch nicht gern gesehen...
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 14 Januar 2017, 10:24:07
Zitat von: Loredo am 14 Januar 2017, 10:17:17
DoTrigger() zählt aber in seiner eigenen Loop nur zu Beginn die Anzahl der Array Elemente und ignoriert daher Änderungen, die während der Loop Verarbeitung gemacht werden.

Das ist zwar korrekt, aber kein Problem. DoTrigger() ermittelt zu beginn die Anzahl der Elemente in $hash->{CHANGED} für die Logmeldung, sowie der Prüfung, ob überhaupt Änderungen in CHANGED enthalten sind. Anschließend werden sämtliche NotifyFn's für alle entsprechenden Empfängerdefinitionen ausgeführt. Diese können dann CHANGED manipulieren (wie bspw. average/dewpoint).

Sobald alle NotifyFn's durchgeführt sind, wird in fhem.pl Zeile 3231 die Anzahl neu bestimmt um dafür die Events für den Inform-Mechanismus (Longpoll) zu erstellen.

Gruß
Markus
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 10:31:14
Demnach sollte ja ein einfaches




    $hash->{NotifyOrderPrefix} = "10-";   # Want to be called before the rest



In X_Initialize() helfen. Tut es aber leider nicht. Sorry, aber ich steh wohl grad aufm Schlauch...
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 14 Januar 2017, 10:46:56
Kannst du mal das vollständige Modul posten, so wie du es eben probiert hast?

Danke

Gruß
Markus
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 10:49:47
Danke, Markus, dass du mal reinschauen willst. Sollte hoffentlich auch recht übersichtlich sein.
Anbei so wie ich es probiert habe.
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 14 Januar 2017, 10:59:59
Wie sehen denn die Debugausgaben aus, welche du überall im Log hast?
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 11:02:40

2017.01.14 11:01:50.582 5: Cmd: >set Livingroom dim100%<
2017.01.14 11:01:50.582 3: FS20 set Livingroom on
2017.01.14 11:01:50.583 5: Triggering Livingroom (1 changes)
2017.01.14 11:01:50.583 5: Starting notify loop for Livingroom, 1 event(s), first is dim100%
2017.01.14 11:01:50.584 1: DEBUG0+++
$VAR1 = [
          'state: on'
        ];
2017.01.14 11:01:50.584 5: powerMap_Notify: Entering for Livingroom
2017.01.14 11:01:50.584 5: powerMap_powerMap: Entering for Livingroom
2017.01.14 11:01:50.584 5: powerMap Livingroom: state: val=on num=100
2017.01.14 11:01:50.584 4: powerMap Livingroom: power = 60
2017.01.14 11:01:50.584 5: powerMap_energy: Entering for Livingroom
2017.01.14 11:01:50.584 4: powerMap Livingroom: energy calculation results:
  energyOld : 0.0169444444444444 Wh
  powerOld  : 0.5 W
  power     : 60 W
  timeframe : 0.0830555555555555 h
  energyDiff: 0.0415277777777778 Wh
  energy    : 0.0584722222222222 Wh
2017.01.14 11:01:50.584 5: powerMap Livingroom: next update in 900 s
2017.01.14 11:01:50.585 1: DEBUG2+++ max=3
$VAR1 = [
          'dim100%',
          'pM_energy: 0.0584722222222222',
          'pM_power: 60'
        ];
2017.01.14 11:01:50.585 5: Triggering pm (1 changes)
2017.01.14 11:01:50.585 5: Starting notify loop for pm, 1 event(s), first is Last device: Livingroom
2017.01.14 11:01:50.586 5: Triggering AllLights (1 changes)
2017.01.14 11:01:50.586 5: Starting notify loop for AllLights, 1 event(s), first is undefined
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 14 Januar 2017, 11:06:01
Ich teste mit fhem.cfg.demo, Device: Livingroom, ergänzt durch:


defmod pm powerMap

attr Livingroom powerMap {\
state => {\
0 => 0.5,\
100 => 60,\
}\
}
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 14 Januar 2017, 15:16:09
Hallo Loredo,

leider konnte ich es nicht schaffen das ganze gründlich zu ergründen aufgrund der Nichterreichbarkeit der Infrastruktur heute. Werde ich mir morgen in Ruhe anschauen.

Was mir soweit aufgefallen ist, dass ich Unit.pm bei mir nicht laden lässt, da in Unit.pm folgendes Statement enthalten ist:

use FHEM::Uconv

erst als ich das in use UConv; änderte, konnte ich powerMap laden. Ich verwende eine andere Ordnerstruktur als normal üblich (Synology Paket), daher liegt fhem.pl komplett woanders als die Module. Da der Modulpfad zu @INC gehört findet er so UConv.pm bei mir wieder korrekt im Modulpfad.

Gruß
Markus
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 15 Januar 2017, 15:34:07
Danke dir, Markus. Hatte ich aber gar nicht mitbekommen ;-)
Das Forum läuft ja glücklicherweise noch woanders  8)


Zitat von: Markus Bloch am 14 Januar 2017, 15:16:09
Was mir soweit aufgefallen ist, dass ich Unit.pm bei mir nicht laden lässt, da in Unit.pm folgendes Statement enthalten ist:

use FHEM::Uconv


Hm, mir war nicht klar, dass jemand die Ordnerstruktur ändern würde.
Jedenfalls ging das seinerzeit nicht ohne FHEM::, keine Ahnung wieso. Habs auch grad entfernt und es scheint zu gehen. Strange!
Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Markus Bloch am 15 Januar 2017, 19:33:47
Hallo Loredo,

nach langer Zeit des Forschens und Debug-Loggings habe ich die Erklärung finden können. Mit folgendem Auszug funktioniert alles wie gewünscht:

    # foreign device events
    foreach my $event ( @{$events} ) {
        next
          if ( !$event
            or $event =~ /^($rname_e|$rname_p): /
            or $event !~ /: / );

        # only recalculate once no matter
        # how many events we get at once
        unless ($powerRecalcDone) {
            my $power = powerMap_powerMap( $name, $dev, $event );
            if ( defined($power) ) {
                $powerRecalcDone = 1;

                unless ( AttrVal( $dev, "powerMap_noEnergy", 0 ) ) {
                    my $energy = powerMap_energy( $name, $dev, $power );
                    readingsSingleUpdate($dev_hash, $rname_e, $energy, 1);
                }

                readingsSingleUpdate($dev_hash, $rname_p, $power, 1);
               
                # recalculate CHANGEDWITHSTATE for target device in deviceEvents()
                $dev_hash->{CHANGEDWITHSTATE} = [];
            }
        }
    }

     #InternalTimer( gettimeofday() + 0.1,
     #    "powerMap_readingsDelayedUpdate", \%readings );

    readingsSingleUpdate( $hash, "state", "Last device: $dev", 1 ) if ($powerRecalcDone);
    return undef;
}


Der Grund, warum die Events für deine pM_*Readings nicht erzeugt wurden, liegt an der Funktion deviceEvents() welche eine Kopie von $hash->{CHANGED} unter $hash->{CHANGEDWITHSTATE} anlegt. Da du diese Funktion aufrufst, befüllt deviceEvents() $hash->{CHANGEDWITHSTATE} mit geändertem "state"-Event.

FHEMWEB wird dann im Laufe des Notify-Vorgangs ebenfalls via NotifyFn aufgerufen. Hier wird ebenfalls deviceEvents() verwendet mit aktiviertem $with_state. Da nun $hash->{CHANGEDWITHSTATE} bereits beim Durchlauf von powerMap erzeugt wurde (und im Normalfall ja auch keine Änderungen stattfinden) wird das zuvor berechnete CHANGEDWITHSTATE an FHEMWEB zurückgegeben (wo die pM_*-Events nicht enthalten sind). Es erfolgt keine Neuberechnung. Daher erhält FHEMWEB nur die alten Einträge, welche vor dem Aufruf von powerMap vorhanden waren.

Daher muss in diesem ganz speziellen Fall in powerMap nach dem erzeugen der Readings/Events $hash->{CHANGEDWITHSTATE} wieder geleert werden. Dadurch erstellt deviceEvents() diesen neu auf Basis der Events, welche in $hash->{CHANGED} vorhanden sind. Da nun die pM-Events existieren, werden diese ebenfalls in CHANGEDWITHSTATE mit übernommen und FHEMWEB erhält diese ebenfalls als Events.

Man könnte in deviceEvents() dieses Caching von CHANGEDWITHSTATE abschalten, oder du musst eben manuell dieses leeren (NICHT löschen!!!).

Durch die Verwendung von den readings*update()-Funktionen werden auch die ganzen Zusatzattribute entsprechend berücksichtigt.

Gruß
Markus

Titel: Antw:Events aus X_Notify() heraus erzeugen
Beitrag von: Loredo am 15 Januar 2017, 19:56:15
Man krass, da wäre ich ja wirklich nie drauf gekommen.  ???

VIELEN VIELEN Dank für die Untersuchung, Sherlock! *thumbsUp*