vorschlag: (optionale) asynchrone ausgabe von get kommandos

Begonnen von justme1968, 08 November 2015, 22:29:06

Vorheriges Thema - Nächstes Thema

justme1968

mit dem hier vorgestellten vorschlag wird es möglich die ausgabe von potentiell länger dauernden get kommandos asynchron zu machen und so fhem nicht auf das fertige kommando warten zu lassen.

die idee ist:

  • in den frontend modulen (telnet, fhemweb, ...) eine FW_DelayedOutput routine hinzuzufügen die dem anwender eine ausgabe zeigen kann,
  • das jeweilige device ($cl) über das ein kommando abgesetzt wurde in die GetFn zu übergeben
  • und dann asynchron sobald eine antwort vorliegt über eine zentrale delayedOutput funktion die meldung an dasjenige eingabe device zu verteilen von dem die anfrage ursprünglich gekommen ist.

ein konkretes beispiel an dem ich gerade arbeite ist ein modul das per HttpUtils_NonblockingGet bestimmte werte abfragt. sobald diese abfrage durch ein get angestossen wird muss ich bis jetzt auf HttpUtils_BlockingGet ausweichen um dem anwender die antwort auch zeigen zu können. mit der hier vorgeschlagenen änderung kann jetzt in meiner GetFn $cl an den non-blocking callback durchreichen und dann die ausgabe asynchron anzeigen sobald sie da ist. ich habe alleine in mindestens 3-4 anderen meiner module dafür verwendung.

die änderungen um die funktionalität einzubauen sind recht klein.

fhem.pl:
hier wird $cl an die GetFn durchgereicht und die delayedOutput funktion eingeführt.Index: fhem.pl
===================================================================
--- fhem.pl (revision 9780)
+++ fhem.pl (working copy)
@@ -1599,12 +1601,32 @@
     }

     $a[0] = $sdev;
+    $defs{$sdev}->{CL} = $cl;
     my $ret = CallFn($sdev, "GetFn", $defs{$sdev}, @a);
+    delete $defs{$sdev}->{CL};
     push @rets, $ret if(defined($ret) && $ret ne "");
   }
   return join("\n", @rets);
}
+sub
+delayedOutput($$)
+{
+  my ($cl,$ret) = @_;

+  return undef if( !$cl );
+
+  if( !$defs{$cl->{NAME}}
+      || $defs{$cl->{NAME}}->{NR} != $cl->{NR}
+      || $defs{$cl->{NAME}}->{NAME} ne $cl->{NAME} ) {
+
+    Log3 $cl->{NAME}, 3, "$cl->{NAME} delayedOutput: device gone, output was: $ret";
+   
+    return undef;
+  }
+
+  $ret = CallFn($cl->{NAME}, "DelayedOutputFn", $defs{$cl->{NAME}}, $ret);
+
+  return $ret;
+}
+


98_telnet.pm:
hier wird die DelayedOutputFn eingeführt die einfach auf das socket schreibt (und auch gleich intern verwendet).Index: 98_telnet.pm
===================================================================
--- 98_telnet.pm (revision 9565)
+++ 98_telnet.pm (working copy)
@@ -17,6 +17,7 @@

   $hash->{DefFn}   = "telnet_Define";
   $hash->{ReadFn}  = "telnet_Read";
+  $hash->{DelayedOutputFn}  = "telnet_Output";
   $hash->{UndefFn} = "telnet_Undef";
   $hash->{AttrFn}  = "telnet_Attr";
   $hash->{NotifyFn}= "telnet_SecurityCheck";
@@ -284,9 +285,26 @@
   $ret .= (join("\n", @ret) . "\n") if(@ret);
   $ret .= ($hash->{prevlines} ? "> " : $hash->{prompt}." ")
           if($gotCmd && $hash->{showPrompt} && !$hash->{rcvdQuit});
+
+  $ret =~ s/\n/\r\n/g if($pw);  # only for DOS telnet
+  telnet_Output($hash,$ret);
+
+  if($hash->{rcvdQuit}) {
+    if($hash->{isClient}) {
+      delete($hash->{rcvdQuit});
+      telnet_ClientDisconnect($hash, 0);
+    } else {
+      CommandDelete(undef, $name);
+    }
+  }
+}
+sub
+telnet_Output($$)
+{
+  my ($hash,$ret) = @_;
+
   if($ret) {
     $ret = utf8ToLatin1($ret) if( $hash->{encoding} eq "latin1" );
-    $ret =~ s/\n/\r\n/g if($pw);  # only for DOS telnet
     for(;;) {
       my $l = syswrite($hash->{CD}, $ret);
       last if(!$l || $l == length($ret));
@@ -295,14 +313,8 @@
     $hash->{CD}->flush();

   }
-  if($hash->{rcvdQuit}) {
-    if($hash->{isClient}) {
-      delete($hash->{rcvdQuit});
-      telnet_ClientDisconnect($hash, 0);
-    } else {
-      CommandDelete(undef, $name);
-    }
-  }
+
+  return undef;
}


01_FHEMWEB.pl:
hier wird eine DelayedOutputFn eingeführt die die ausgabe in einem jQuery popup anzeigt.Index: 01_FHEMWEB.pm
===================================================================
--- 01_FHEMWEB.pm (revision 9780)
+++ 01_FHEMWEB.pm (working copy)
@@ -119,6 +119,7 @@
   my ($hash) = @_;

   $hash->{ReadFn}  = "FW_Read";
+  $hash->{DelayedOutputFn}  = "FW_DelayedOutput";
   $hash->{GetFn}   = "FW_Get";
   $hash->{SetFn}   = "FW_Set";
   $hash->{AttrFn}  = "FW_Attr";
@@ -476,6 +477,19 @@
}

sub
+FW_DelayedOutput($$)
+{
+  my ($hash, $ret) = @_;
+
+  $ret = "<pre>$ret</pre>" if($ret =~ m/\n/ );
+  $ret =~ s/\n/<br>/g;
+  my $data = FW_longpollInfo('JSON', "#FHEMWEB:$hash->{NAME}","FW_okDialog('$ret')","");
+  addToWritebuffer($hash, $data."\n");
+
+  return undef;
+}
+
+sub
FW_closeConn($)
{
   my ($hash) = @_;


das ganze lässt sich auch auf andere frontends ausdehnen und im prinzip auch für asynchrone, modul übergreifende GetFn aufrufe verwenden, funktioniert aber natürlich nur wenn es auch in einem modul verwendet wird das die Abarbeitung des kommandos selber asynchron erledigt.

diskussionspunkte:
- für das durchreichen von $cl ist mir keine elegantere methode eingefallen die funktioniert ohne die signatur zu ändern.
- ist es sinnvoll das auch für set einzubauen?
- man könnte noch eine überschrift einblenden zu welchem kommando die ausgabe gehört und wie lange es gedauert hat.

gruss
  andre

edit: es gibt noch ein unstimmigkeit mit fhemweb: beim absetzen des get über das drop down menü und klick auf 'get' erscheint das popup mit der antwort nicht, nur bei eingabe eines get kommandos in maininput text feld. ich bin mir noch nicht sicher woran es liegt aber vermutlich wird statt dem fhemweb device das zur aktuellen seite gehört das wenige verwendet das zum ihr get kommando gehört. ideen wie das zu lösen ist?

edit2: eine mögliche lösung ist wie beim trigger <web> JS:... die ausgabe an alle devices mit $FW_wname als $hash->{SNAME} zu senden. das hat aber den nachteil das die ausgabe an allen offenen fenstern erscheint.

vorschlag: in den <body> tag jeder seite wird eine eindeutige id generiert die die seite identifiziert und die über FW_cmd und FW_answerCall wieder zurück gegeben wird so das die ausgabe des get eindeutig einer seite zugeordnet werden kann.

edit3: die idee jedes offene fhemweb fenster mit einer eindeutigen id zu versehen funktioniert gut.

01_FHEMWEB.pl:
im body tag jeder fhemweb seite wird ein eindeutiges fw_id attribut erzeugt. dieses wird im XHR header wieder zurück gegeben und in der zur longpoll verbindung gehörenden fhemweb device gespeichert. in FW_DelayedOutput wird dann die longpoll verbindung gesucht die zum fhemweb fenster gehört in dem das get kommando erzeugt wurde.Index: 01_FHEMWEB.pm
===================================================================
--- 01_FHEMWEB.pm       (revision 9780)
+++ 01_FHEMWEB.pm       (working copy)
@@ -106,6 +106,7 @@
my %FW_hiddengroup;# hash of hidden groups
my $FW_inform;
my $FW_XHR;        # Data only answer, no HTML
+my $FW_id;         # id of current page
my $FW_jsonp;      # jasonp answer (sending function calls to the client)
my $FW_headercors; #
my $FW_chash;      # client fhem hash
@@ -119,6 +120,7 @@
   my ($hash) = @_;

   $hash->{ReadFn}  = "FW_Read";
+  $hash->{DelayedOutputFn}  = "FW_DelayedOutput";
   $hash->{GetFn}   = "FW_Get";
   $hash->{SetFn}   = "FW_Set";
   $hash->{AttrFn}  = "FW_Attr";
@@ -278,6 +280,7 @@

   $FW_chash = $hash;
   $FW_wname = $hash->{SNAME};
+  $FW_id = $hash->{NR};
   $FW_cname = $name;
   $FW_subdir = "";

@@ -476,6 +479,26 @@
}

sub
+FW_DelayedOutput($$)
+{
+  my ($hash, $ret) = @_;
+
+  $ret = "<pre>$ret</pre>" if($ret =~ m/\n/ );
+  $ret =~ s/\n/<br>/g;
+  foreach my $d (keys %defs ) {
+    my $chash = $defs{$d};
+    next if( $chash->{TYPE} ne 'FHEMWEB' );
+    #next if( $chash->{SNAME} ne $FW_wname );
+    next if( !$chash->{FW_ID} || $chash->{FW_ID} ne $FW_id );
+    my $data = FW_longpollInfo('JSON', "#FHEMWEB:$FW_wname","FW_okDialog('$ret')","");
+    addToWritebuffer($chash, $data."\n");
+    last;
+  }
+
+  return undef;
+}
+
+sub
FW_closeConn($)
{
   my ($hash) = @_;
@@ -603,6 +626,7 @@

   if($FW_inform) {      # Longpoll header
     if($FW_inform =~ /type=/) {
+      $me->{FW_ID} = $FW_id;
       foreach my $kv (split(";", $FW_inform)) {
         my ($key,$value) = split("=", $kv, 2);
         $me->{inform}{$key} = $value;
@@ -782,7 +806,7 @@
   my $csrf= ($FW_CSRF ? "fwcsrf='$defs{$FW_wname}{CSRFTOKEN}'" : "");
   my $gen = 'generated="'.(time()-1).'"';
   my $lp  = 'longpoll="'.AttrVal($FW_wname,"longpoll",1).'"';
-  FW_pO "</head>\n<body name=\"$t\" $gen $lp $csrf>";
+  FW_pO "</head>\n<body name=\"$t\" fw_id=\"$FW_id\" $gen $lp $csrf>";

   if($FW_activateInform) {
     $cmd = "style eventMonitor $FW_activateInform";
@@ -902,6 +926,7 @@
     if($p eq "XHR")          { $FW_XHR = 1; }
     if($p eq "jsonp")        { $FW_jsonp = $v; }
     if($p eq "inform")       { $FW_inform = $v; }
+    if($p eq "fw_id")        { $FW_id = $v; }

   }
   $cmd.=" $dev{$c}" if(defined($dev{$c}));


fhemweb.js:
der inhalt des fw_id attributes aus dem body tag wird im FW_cmd header übergeben.
Index: fhemweb.js
===================================================================
--- fhemweb.js (revision 9035)
+++ fhemweb.js (working copy)
@@ -223,6 +223,7 @@
{
   log("FW_cmd:"+arg);
   arg = addcsrf(arg);
+  arg += '&fw_id='+document.body.getAttribute('fw_id');
   var req = new XMLHttpRequest();
   req.open("POST", arg, true);
   req.send(null);


ich vermute die eindeutige zuordnung von auslösendem fhemweb fenster zur zugehörigen longpoll verbindung kann auch noch an anderer stelle nützlich sein.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Die grundsaetzliche Idee finde ich gut, und ich werde es auch einbauen.
Was mir noch unklar ist, wie man zwischen Benutzereingabe und Programmaufruf unterscheidet, z.Bsp. wenn jemand get per HTTP Link aus einem externen Programm aufruft.

justme1968

in der url die für den externen aufruf erzeugt wird fehlt der fw_id parameter. diesen gibt es nur wenn die url über FW_cmd aus einer interaktiv verwendeten web seite erzeugt wird.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

#3
vorschlag: im $cl das an die GetFn durchgereicht wird könnten wir noch ein $hash->{canDelayedUpdate} einbauen. das wäre bei telnet immer true, bei fhrmweb nur wenn es interaktiv durch klick zustande gekommen ist.

das kann das modul in der GetFn entscheiden ob es im nicht interaktiven fall auf blockieren zurück fällt oder ob die rückgabe dann ins leere läuft.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

ich bin gerade dabei den patch zu überarbeiten und vollständig zu machen. von meiner seite aus gibt es erst mal nur noch eine stelle die eine frage aufwirft:

das verhalten bei eingabe eines get kommandos in das maininput textfeld: bisher erfolgt nach der eingabe ein redirect auf die hauptweite und es wird eine neue longpoll verbindung aufgemacht. das zuordnen der neuen verbindung zum kommando habe ich zwar inzwischen im griff aber es gibt eine racecondition wenn das kommando schneller abgearbeitet wird als die longpoll verbindung aufgebaut wird.

mir fallen zwei mögliche lösungen ein. fhem merkt das es noch keine longpoll verbindung gibt und verzögert die ausgabe so lange bis die verbindung wieder steht oder das get wird wie die 'anklickbaren' get in der detail ansicht per xhr abgewickelt ohne redirect und neuaufbau der seite.

ersteres habe ich noch nicht vollständig probiert, es versucht aber nur das symptom zu umgehen und es ist unschön die seiten id durch den redirect zu retten.

letzteres hat den zusätzlichen vorteil das durch den wegfall des seitenaufbaus alles effizienter ist und sogar besser aussieht.

welche variante bevorzugst du ?
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

#5
anbei die aktuelle (und umbenannte) version des vorschlags.

für das redirect problem habe ich doch noch eine ziemlich einfache lösung gefunden und eingebaut.

den umbau des get auf xhr habe ich in fhemweb.js aber trotzdem drin gelassen. ich finde die bedienung ist sehr viel angenehmer ohne das seiten zappeln und die umleitung auf die haupt seite.

der patch umfasst (wie schon oben beschrieben) folgendes:

  • in die GetFn wird über $hash->{CL} das eingabedevice übergeben von dem aus das get kommando abgesetzt wurde

  • es gibt eine asyncOutput routine mit der asynchron eine ausgabe auf ein solches (gemerktes) client device erfolgen kann

  • in telnet und fhemweb ist jeweils eine passende AsyncOutputFn implementiert

  • der GetFn wird in $hash->{canAsyncOutput} übergeben ob das eingabedevice die asynchrone ausgabe potentiell unterstützt.
    ein fhem modul das die asynchrone ausgabe für get kommandos unterstützen will hat so die möglichkeit zu entscheiden ob es im nicht-interaktiven fall auf blocking zurück fällt oder die rückgabe dann verworfen wird.

für telnet ist das ganze straightforward, da die verbindung auf der ein get rein kommt auch für die ausgabe zuständig ist.

in fhemweb ist es etwas anders da die ausgabe nicht auf der gleichen verbindung erfolgt. die zuordnung geschieht hier anhand eines fw_id parameters der für zusammengehörende anfragen jeweils gleich ist und im seiten body und allen relevanten verbindungen enthalten ist.

frontends die den bestehenden longpoll mechanismus verwenden können mit passend gesetztem fw_id parameter im request der longpoll verbindung und im abgesetzten get kommando die zuordnung erreichen, andere frontends können bei bedarf recht einfach nachziehen und anhand der beiden beispiele eine passende AsyncOutputFn implementieren.


unabhängig von der asynchrone ausgabe hat die übergabe von $hash->{CL} übrigens den netten nebeneffekt das es in der GetFn nun möglich ist gezielt text oder html rückgabe zu erzeugen je nach dem ob die rückgabe für telnet oder web sein soll. im neuen plex modul das ich gerade baue kann ich per get so z.b. die info zu titeln oder playlisten inklusive cover bilden anzeigen wenn die ausgabe im browser erfolgt. 
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Zitatbisher erfolgt nach der eingabe ein redirect auf die hauptweite und es wird eine neue longpoll verbindung aufgemacht.

Das kann ich nicht unterschreiben, und per Test gerade geprueft: bei get bleibt man auf der Detailseite, und man bekommt das Ergebnis in einem Dialog.

justme1968

der dialog kommt nur wenn man das get über die per makeSelect erzeugte get zeile mit get button, drop down menü und das text feld daneben auslöst. die hatten wir bei der großen fhemweb umstellung auf xhr umgebaut.

wenn man das get über freitext eingabe in der maininput zeile auslöst erfolgt bis jetzt ein normales form post auf das in fhemweb mit einem redirect auf die hauptweite geantwortet wird in der dann die rückgabe angezeigt wird. (ich habe in der rückgabe noch < durch &lt; ersetzt damit das auch für rückgaben wie 'usage: get <device> detail <key>' funktioniert.) hier wird bis jetzt nur shutdown abgefangen und nicht per post sondern per xhr weitergeleitet.

mit dem patch wird jetzt auch get abgefangen, per xhr weitergeleitet und das ergebniss entweder in einem dialog angezeigt oder direkt auf der hauptseite falls man sich noch dort befindet.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Du bist so aktiv bei den Aenderungen. Soll ich noch ein/zwei Tage warten, bis es "abgehangen" ist?
:)

justme1968

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

in der ersten version war noch ein tippfehler. der ist inzwischen korrigiert: http://forum.fhem.de/index.php/topic,43771.msg357870.html#msg357870.

ansonsten funktioniert das ganze so stabil das ich mich interaktiv durch eine komplette plex mediathek suchen/klicken kann ohne das fhem dabei auch nur im geringsten blockiert. auch wenn zum teil abfragen an den plex server dabei sind die mehrere sekunden bis zur antwort brauchen.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Ich habe dein Patch durchgelesen.
Da ich mich noch mit Testen schwer tue: stimmt, dass bei einem get im telnet erst der Prompt kommt, und dann die Antwort? Und gibt es eine elegante Moeglichkeit im Modul beide Varianten Varianten zu unterstuetzen? Das eine muesste vom globalen select die Daten holen, der andere vom lokalen.

justme1968

bei telnet funktioniert es wie auf einer unix shell wenn du ein kommando in den hintergrund schickst. du bekommst sofort ein prompt und die ausgabe erscheint einfach irgendwann später. bei der interaktiven verwendung ist das völlig unproblematisch und funktioniert wirklich gut.

ich verwende fhem per telnet übrigens immer ohne prompt (ich vermute zwar das ist eigentlich ein bug :), bin aber dagegen das zu ändern). da fällt es nicht auf.

im vordergrund könnte/kann man sogar weiterarbeiten. im gegensatz zur unix konsole werden die ausgaben dabei auch nicht vermischt da es nicht mehrere prozesse sind. es erscheint immer eine ausgabe komplett.

wenn es dir um den prompt an sich und das aussehen geht: man könnte einfach am ende der AsyncOutputFn im telnet modul noch mal einen prompt ausgeben. dann muss man nur das gemeinsame verwenden von telnet_Output in telnet_Read und AsyncOutputFn ändern oder rückbauen. das kann ich gerne machen.

ich hatte anfangs geplant das ein modul über die initiale get rückgabe signalisieren kann das die ausgabe später kommt so das man etwas anzeigen oder in dem einen telnet fenster warten kann. das zieht aber diverse probleme nach sich falls die ausgabe dann aus irgend einem grund doch unterbleibt. ich bin inzwischen der meinung das es gar nicht so kompliziert sein muss. die aktuelle version ist einfach und transparent.

ich bin mir nicht sicher was du mit lokalem select meinst. es gibt doch nur ein einziges select in fhem. ein zusätzliches lokales select würde nichts gutes bewirken.

ich verwende den aktuellen stand jetzt seit einiger zeit und es funktioniert perfekt für get ausgaben die im bereich von fast sofort bis hin zu 10-20 sekunden kommen. als benutzer wartet man in der regel auf eine solche ausgabe. und selbst wenn nicht funktioniert es gut.

probier mal das hier um ein gefühl dafür zu bekommen:
- ein readingsProxy:define rp readingsProxy rp
attr rp getFn { my $delay = (ord($CMD)-97)*3;;\
\   
  if( $hash->{CL} && $hash->{CL}->{canAsyncOutput} ) {\   
    $hash->{cl} = $hash->{CL};;\
    InternalTimer(gettimeofday()+$delay, "delayed", $hash, 0);;\
    return undef;;\
  }\   
\   
  return ("would wait $delay", 1 );\
}     
attr rp getList a b c
attr rp room rp

- für 99_myUtils.pm:sub                                           
delayed($)                                   
{                                             
  my ($hash) = @_;                           
                                             
  asyncOutput( $hash->{cl}, "test\ntest\ntest\n" );
}                                             


get rp a liefert sofort etwas zurück
get rp b nach etwa 3 sekunden
get rp c nach etwa 6 sekunden
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Danke fuers Beispiel, habs eingecheckt.

Zitatdu bekommst sofort ein prompt und die ausgabe erscheint einfach irgendwann später.
Das habe ich ja befuerchtet, ist nicht wirklich mein Ding. Da ich mit prompt arbeite, bringt das meine Ausgabe durcheinander. Ist aber zunaechst egal.

Zitatich verwende fhem per telnet übrigens immer ohne prompt
Ich vermute, du tippst kein <return> in einer leeren Zeile.

Zitatdie aktuelle version ist einfach und transparent.
Ist mir auch lieber.

Zitates gibt doch nur ein einziges select in fhem.
Traeumer :)
Ueberall, wo ich meine Finger drin hatte (00_CUL.pm, 00_FBAHA, 00_ZWDongle) wird get mit einem lokalen select realisiert. Das es nicht gut ist, daemmert mir auch :) , deswegen ja die Frage. Im ZWave ist es am schlimmsten, weil es inzischen auch programmatisch verwendet wird, um von der Gegenseite secNonce zu holen, und mein Co-Autor weigert sich vom get Abschied zu nehmen. Aber auch im CUL ist das stoerend (get RFR ccconf), ist nur bisher nicht so stark aufgefallen.

justme1968

wie gesagt: den (kosmetischen) prompt kann man wieder herstellen wenn man am ende der telnet AsyncOutputFn einfach noch mal einen prompt ausgibt.

ZitatIch vermute, du tippst kein <return> in einer leeren Zeile.
niemals absichtlich und wenn es aus versehen passiert beende ich schnell und starte eine neue session :). der prompt ist bei copy&paste nur im weg.

ach so. die select meinst du :). das sind aber nicht wirklich 'echte' select sondern nur warten mit timeout und eigentlich kaum besser als blockieren da nur auf einen filedescriptor gewarnt wird. da passiert nichts wirklich asynchron. der rest vom system schläft ja.

mit dem patch könnte man die problematischen get vielleicht auch asynchron machen. auch programm intern oder zwischen modulen wenn man in $hash->{CL} ein 'privates' device oder auch nur einen hash übergibt der einem dann später über asyncOutput wieder aufruft. das würde dann wie eine art callback funktionieren. das ist zwar nicht so schön wie in node.js mit closueres und bind funktioniert aber trotzdem.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Habe zwei Probleme gefixt, die mit dem Patch reinkamen:

1. http://forum.fhem.de/index.php/topic,44357.msg
Lag an direktem Zugriff mit $FW_id, ohne Pruefung. Mein Fix hat vermutlich keine Nebenwirkungen, aber bitte testen.

2. http://forum.fhem.de/index.php/topic,44360.msg
Lag an escapen der < in dem get Antwort, komischerweise nur einmal, und nur <, nicht aber > usw. Das habe ich jetzt komplett entfernt, auch wenn ich nicht weiss, was du damit bezweckt hast. Lustig: der Code zum umwandeln von Geraetenamen in Links stammt auch von dir :)

justme1968

#17
die 1. verstehe ich nicht ganz. könnte passieren wenn eine longpoll verbindung rein kommt bevor das erste mal eine browser seite aufgebaut wurde. aber eigentlich auch dann nicht weil die id über die longpoll verbindung mit geschickt wird...

ich glaube es würde reichen $FW_id am anfang einfach auf 0 zu initialisieren. deine version sollte aber auch gehen.

die 1. war mein fehler und passiert wenn die verbindung nicht aus dem browser kommt. dein fix passt.


die 2. hat einen grund den ich weiter oben kurz erklärt habe. wenn ein text kommt in dem ein < vor kommt wie z.b. wenn das get mit einer 'usage: get ...<wert>' meldung antwortet erscheint nur ein leerer dialog ohne text.

laut html spezifikation ist es eigentlich so das > nur dann eine spezielle bedeutung hat wenn davor ein < auf gleicher ebene kommt. d.h. wenn man das < durch &lt; ersetzt hat das > danach keine spezielle bedeutung mehr und wird einfach angezeigt. vermutlich wäre es aber sauberer das > auch noch durch &gt; zu ersetzen.

eine ursache für das problem ist glaube ich das es in 01_FHEMWEB vier stellen gibt an denen daten an den browser geliefert werden und alle vier werden unterschiedlich behandelt. die erste ist der FW_jsonp fall. hier wird nur neweline escaped. der zweite ist kurz darunter, hier werden mit FW_addLinks links eingefügt. der dritte ist der andere aufruf von FW_addLinks, hier wird auch noch FW_htmlEscape ausfgerufen und kurz darüber der vierte an dem eine mit html markierte rückgabe unverändert durchgereicht wird.

die korrekte lösung ist vermutlich wie an anderen stellen auch die rückgabe mit den ergänzten links durch ein umschliessendes <html>...</html> zu markieren. und nur in dann in fhemweb.js das ersetzen bleiben zu lassen.



hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

A.Harrenberg

Hi Rudi,
Zitat von: rudolfkoenig am 18 November 2015, 20:08:08
Ueberall, wo ich meine Finger drin hatte (00_CUL.pm, 00_FBAHA, 00_ZWDongle) wird get mit einem lokalen select realisiert. Das es nicht gut ist, daemmert mir auch :) , deswegen ja die Frage. Im ZWave ist es am schlimmsten, weil es inzischen auch programmatisch verwendet wird, um von der Gegenseite secNonce zu holen, und mein Co-Autor weigert sich vom get Abschied zu nehmen. Aber auch im CUL ist das stoerend (get RFR ccconf), ist nur bisher nicht so stark aufgefallen.
hab' das erst jetzt entdeckt...

Ich kann jetzt nicht sagen das ich die Diskussion hier überblicke, dafür stecke ich (noch) nicht tief genug drin, vor allem "select" mit Filehandle sagt mir jetzt gerade nicht sehr viel, außer das man damit das System durchaus blockiert...

Meine "Weigerung" get abzuschaffen bezieht sich ja erst mal nur auf die Unterscheidung der Befehle in SET und GET um zu wissen ob eine Antwort erwartet wird oder nicht. Die momentane Bearbeitung der get-Befehle mit dem Aufruf der "ReadAnswerFn" in ZWDongle (dort passiert dann ja das select) brauche ich eigentlich nicht für die SECURITY Sachen. Wenn Du also an der Stelle umbauen möchtest sollte das eigentlich keine weiteren Konsequenzen für SECURITY haben.

Ich seh' aber schon das ich mich hier doch noch deutlich tiefer mit den internen Abläufen von FHEM beschäftigen muss.

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

rudolfkoenig

Das $hash->{CL} wird jetzt auch by define/modify gesetzt.
Im at wird damit bei einem wiederkehrenden at die Pruefung vermieden.
Auch wenn ein at in einem notify definiert wird, wird nicht geprueft.