Ankündigung

Einklappen
Keine Ankündigung bisher.

Universalclient

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Universalclient

    Ich denke es ist geschickt die Diskussion aus cometvisu-client.js überschreiben ohne hardcodierten UrlPrefix? hier fort zu führen. Denn das ursprüngliche Thema hat sich ja etwas geändert.

    Nun, um was geht es hier? Es geht um das zusammenführen und vereinheitlichen der "Clientimplementierungen" in der CV. Bis dato gab es eine für knxd und OpenHAB, sowie eine weitere für OpenHAB2.

    Um die Sache kompatibler und ausbaufähiger zu machen, hat sich peuter hingesetzt und mit einer Universalclient-Implementierung begonnen:
    https://github.com/peuter/CometVisu/...rsal-client.js



    #2
    Ich hab mich gestern Abend mal mit Tobias' Implementierung beschäftigt und etwas erweitert:

    Wie bisher, kann man in der visu-config z.B. backend="oh" einstellen. Damit wird dann auf eine hard-codierte Einstellung zurückgegriffen die die Transport-Art (Long-Polling, SSE, ...) sowie den UrlPrefix einstellt.

    Neu wäre jetzt, dass man stattdessen auch backend_url="/meinbackend/" bzw. backend_url="http://localhost/meinbackend/" angeben kann und der Client dann aus dem Login-Response versucht, alle notwendigen Infos für die weitere Kommunikation mit dem Backend zu gewinnen.
    Das Backend beantwortet den Login dann z.B. so:

    Code:
    {
        "s":"da458506-550c-4c0a-a432-597bd464da42",
        "c":{
            "name":"KnxAutomationDaemon",
            "transport":"sse",
            "resources":{
                "read":"r",
                "rrd":"rrdfetch",
                "write":"w"
            }        
        },
        "v":"0.0.1"
    }
    In "c" ist die Konfiguration des Backends beschrieben.

    Damit kommen wir langfristig weg von den ganzen hard-codierten Einstellungen in der CV und kommen hin zu einem Backend, das selbst bekannt gibt wie es genutzt werden möchte.

    Ich hab gestern dann noch den re-connect im Fall eines Verbindungsabbruchs im SSE Transport modifiziert. So im Test hat das gut geklappt. Was nicht klappt:

    Das Android-Endgerät (Smartphone, Smartdisplay wie Xoro Megapad, ...) geht früher oder später schlafen und wird ggf. durch z.B. WOLI bei Bedarf aufgeweckt.
    Dabei scheint der JS Interpreter oder so einzufrieren und erst wieder aufzuwachen, wenn man die Visu-Seite neu lädt.

    Ich bin noch dabei das zu untersuchen. Mein Backend schickt eigentlich alle 2sek über die SSE-Verbindung ein Update mit einem "Heartbeat"

    Code:
    {"d":{"KAD.CV.heartbeat":"1"},"i":"1"}
    {"d":{"KAD.CV.heartbeat":"0"},"i":"1"}
    {"d":{"KAD.CV.heartbeat":"1"},"i":"1"}
    {"d":{"KAD.CV.heartbeat":"0"},"i":"1"}
    um die SSE Verbindung zu testen (benutze ich um serverseitig die Session bei Abbruch der Verbindung zu invalidieren). Aber der kommt nach dem Aufwecken des Geräts nicht mehr an. Und die SSE-Implementierung im Client meldet auch keinen Zusammenbruch der Verbindung. Es tut sich einfach nichts mehr. Eingefroren...

    Kennt jemand dieses Phänomen aus dem Long-Polling Variante? Dort wird ja pro-aktiv vom Client über den Watchdog sicher gestellt, dass immer mal wieder ein Request zum Server aufgemacht wird. Friert das auch ein, oder läuft das wieder an wenn man das Android-Gerät wieder aufweckt und in das bereits vor-geladene Browser-Tab wechselt?

    Meine aktuelle Code-Anpassung des Universalclients findet man hier: https://github.com/tuxedo0801/CometV...iversal-client

    Kommentar


      #3
      Mittlerweile habe ich mit ADB Logcat auf mein Nexus4 geschaut um zu beobachten was passiert. Aber auch hier kommt nicht mehr zum Vorschein. Irgendwann friert die Geschichte ohne Fehler einfach ein und wacht erst auf, wenn ich im Browser einen reload mache (es hilft auch nicht in der Visu zu navigieren oder zu versuchen etwas zu verstellen).

      Sehr seltsam. Werde als nächstes mal versuchen einen Watchdog für SSE einzubauen der zyklisch die Verbindung prüft. Mal schauen ob der das "schlafenlegen" überlebt.

      Kommentar


        #4
        *ping*

        Gibt's hier keine Android-Tablet-User die ihre Visu bei Abwesenheit schlafen legen?

        peuter
        ​hast du das bei dir schon mal mit SSE probiert?

        Kommentar


          #5
          Zitat von tuxedo Beitrag anzeigen
          ​hast du das bei dir schon mal mit SSE probiert?
          Auch wenn die Antwort ein bisschen spät kommt (sorry ist mit irgendwie durchgerutscht): Ich habe openHAB2 (und damit auch SSE) noch nicht produktiv bei mir im Einsatz (ist ja auch noch alpha). Daher habe ich damit auch noch keine Langzeit Erfahrungen gemacht was Verbindungsabbrüche angeht. Kann ich also nicht wirklich weiterhelfen.

          Nun zum eigentliche Post:
          Ich habe jetzt endlich mal die Zeit gefunden den Universal Client weiterzuentwickeln, im Wesentlichen habe ich es so umgesetzt wie in diesem und dem anderen Thread vorgeschlagen, bis auf kleinere Anpassungen. Was vom Login zurückkommt sieht bei openhab2 nun so aus:

          Code:
          {
              "s":"da458506-550c-4c0a-a432-597bd464da42",
              "c":{
                  "name":"openhab2",
                  "transport":"sse",
                  "urlPrefix":"/rest/cv/"
                  "resources":{
                      "read":"r",
                      "rrd":"rrdfetch",
                      "write":"w"
                  }        
              },
              "v":"0.0.1"
          }
          Und der Header der mit den Config-Files gesendet werden kann / muss sieht so aus:

          Code:
          X-CometVisu-Backend: /rest/cv/l;openhab2
          wobei das ";openhab2" optional ist, soll einfach nur dem Backend die Möglichkeit geben sich namentlich zu melden. Testweise funktioniert das Ganze mit openhab2. Feine Sache ;-) Bitte um Anregungen ob wir das jetzt so festklopfen sollten oder ob es eventuell noch was anzupassen gibt an den genutzten Formaten / Namen.

          Der Vollständigkeit halber nochmal Links zu den Sourcen:

          https://github.com/peuter/CometVisu/...iversal-client
          https://github.com/peuter/openhab2/tree/cometvisu2
          Gruß
          Tobias

          Kommentar


            #6
            Prima. hab nur 2 Anmerkungen:

            Würde den Parameter im Login-Response nicht "urlPrefix", sondern einfach URL nennen. Technisch würde ich schauen, dass beides geht: absolute (http://....) und relative URL (/rest/...).

            Zum Header:
            Find ich gut dass du die Idee mit dem Namen des Backens vor bringst. Aber hier haben wir doch allen Platz der Welt. Wieso wieder zwei Dinge in einen Parameter verpacken?
            Gegenvorschlag:

            * X-CometVisu-Backend-URL: /rest/cv/ <---- Hier wieder die URL, absolut oder relativ, aber nicht direkt auf den Login, sonder auf den basispfad bezogen --> Konsistenz zum Login-Response
            * X-CometVisu-Backend-Name: openhab2

            bzgl. SSE und Android/mobilen Endgeräten: Sieht tatsächlich so aus, als ob der Browser nach dem Display-Sleep tatsächlich stillschweigend die SSE Verbindung kappt und keinen Fehler auslöst (welcher die Verbindung neu aufbauen lassen würde). Habs immer noch nicht ausprobiert, aber ich vermute hier muss man tatsächlich eine Art Heartbeat/Watchdog laufen lassen der die Verbindung überprüft und im Fehlerfall die SSE Verbindung neu aufbaut. Wäre super wenn du das bei dir auch mal ausprobieren könntest, so dass wir hier zeitnah eine Lösung finden, damit's mit dem Universalclient vorwärts geht.

            Abgesehen von diesem Detail läuft der Client ganz gut.

            Gruß
            Alex

            Kommentar


              #7
              Zitat von tuxedo Beitrag anzeigen
              Würde den Parameter im Login-Response nicht "urlPrefix", sondern einfach URL nennen. Technisch würde ich schauen, dass beides geht: absolute (http://....) und relative URL (/rest/...).
              Das ist ja nur eine "Teil-URL" von daher fände ich nur url etwas unpassend. Vielleicht "baseURL"?
              Mir fällt jetzt nichts ein warum absolute Pfade bei der bisherigen Implementierung nicht gehen sollten. Ist also sozusagen schon "drin". Problem wird hier sein, das der Client keinen Ajax-Request an eine andere Domain schicken kann (Stichwort: Cross-Origin).

              Zitat von tuxedo Beitrag anzeigen
              * X-CometVisu-Backend-URL: /rest/cv/ <---- Hier wieder die URL, absolut oder relativ, aber nicht direkt auf den Login, sonder auf den basispfad bezogen --> Konsistenz zum Login-Response
              Der Client braucht aber den Pfad zum Login, daher fehlt in diesem Fall eine Information. Außer wir geben fest vor dass das Login immer unter "l" zu finden sein muss, finde ich aber nicht gut das fest zu definieren. Andernfalls bräuchte man noch einen dritten Header der auch den relativen Pfad zur Login-Resource definiert. Und das auf 3 Header zu verteilen finde ich doch übertrieben. Mit den vorgeschlagenen 2 Header kann ich leben, wobei die vorgeschlagene Lösung durchaus der gängigen Praxis entspricht mehrere Informationen in einen Header per Semikolon getrennt zu packen. Vor allem wenn die Daten so "klein" sind, dass es sich eigentlich nicht lohnt dafür einen 2. Header zu senden.

              Zitat von tuxedo Beitrag anzeigen
              bzgl. SSE und Android/mobilen Endgeräten: Sieht tatsächlich so aus, als ob der Browser nach dem Display-Sleep tatsächlich stillschweigend die SSE Verbindung kappt und keinen Fehler auslöst (welcher die Verbindung neu aufbauen lassen würde).
              Ich versuche das mal zu debuggen, auf den ersten Blick kann man sehen, das EventSource.readyState = 2 wird (was heißt, dass die Verbindung geschlossen wurde. Das muss man nur noch mitkriegen, bzw. beim Wakeup des Devices prüfen ob die Verbindung besteht und ggf. neu Verbinden, oder halt im Watchdog prüfen und neu Verbinden, je nachdem was am besten geht.
              Gruß
              Tobias

              Kommentar


                #8
                Das ist ja nur eine "Teil-URL"
                Bis jetzt, ja. Aber wenn man sich den ModProxy sparen will, wäre eine komplette URL äußerst brauchbar. Und in meinem Fall sogar essentiell wichtig. Nicht unbedingt beim Login-Response, sondern eher im Header. Aber aus konsistenzgründen würde ich in beiden Fällen das Verhalten identisch halten.

                Mir fällt jetzt nichts ein warum absolute Pfade bei der bisherigen Implementierung nicht gehen sollten.
                Korrekt, ist drin und funktioniert. Aber der Name suggeriert eben dass nur ein Prefix möglich ist. Deshalb der Namensvorschlag "Url", der absolut und relativ sein kann.

                Problem wird hier sein, das der Client keinen Ajax-Request an eine andere Domain schicken kann (Stichwort: Cross-Origin).
                Andere Domain könnte Problematisch sein, aber anderer Port? Bei mir funktioniert das bis jetzt ganz gut.



                Der Client braucht aber den Pfad zum Login, daher fehlt in diesem Fall eine Information.
                Hast recht. Wir sind ja noch nicht beim Login und müssen erst noch zum Login.

                Dann vllt. doch lieber "X-CometVisu-Backend-LoginUrl" ??


                Ich versuche das mal zu debuggen, auf den ersten Blick kann man sehen, das EventSource.readyState = 2 wird (was heißt, dass die Verbindung geschlossen wurde.
                Jepp, das seh ich auch wenn ich einen Verbindungabbruch forciere (Netzwerkkabel z.b. raus ziehen). Wenn das Device aber schlafen geht und wieder aufwacht, scheint Android zumindest keinerlei anstalten zu machen und einen Verbindungsabbruch mit einer state-änderung zu signalisieren. Der macht einfach gar nix.

                Das muss man nur noch mitkriegen, bzw. beim Wakeup des Devices prüfen ob die Verbindung besteht und ggf. neu Verbinden, oder halt im Watchdog prüfen und neu Verbinden, je nachdem was am besten geht.
                Kriegt man mit JS so ein Geräteaufwachen denn mit? Wenn ja wäre das ja des rätsels lösung. Ansonsten halt Watchdog.

                Hatte hier schonmal was probiert:

                Das Backend antwortet mit einer Dummyadresse und einem Dummywert alle X sekunden, sofern sich sonst nix tut und keine Events anstehen. Der Client bekommt also spätestens alle X sekunden ein event. Entweder Daten, oder die Dummy-Daten. Bleiben die Events für zeitraum X aus, so wird neu verbunden.

                Hatte das mit einem nebenläufigen Thread (html5 ...) umgesetzt, aber zwischenzeitlich wieder verworfen (weil dann doch nicht gebraucht). Und jetzt sieht's danach aus als könnte man's wieder gebrauchen.
                Allerdings bin ich mir nicht sicher ob das so toll ist wenn das backend den "KeepAlive" macht und der Client einfach davon abhängt. Andersrum wäre mir es lieber, aber da sind dann wieder extra GET-Requests im Spiel.



                Kommentar


                  #9
                  Zitat von tuxedo Beitrag anzeigen

                  Bis jetzt, ja. Aber wenn man sich den ModProxy sparen will, wäre eine komplette URL äußerst brauchbar. Und in meinem Fall sogar essentiell wichtig. Nicht unbedingt beim Login-Response, sondern eher im Header. Aber aus konsistenzgründen würde ich in beiden Fällen das Verhalten identisch halten.
                  Mit Teil-URL meinte ich, dass man da immer noch den read/write/rrd Pfad dranhängen muss um eine komplette URL zum Backend zu bekommen. Von daher ist es ein prefix. Wie schon vorgeschlagen würde ich das dann baseURL nennen, das suggeriert zumindest aus meiner Sicht nicht, dass man da nicht auch ne absolute URL angeben kann.

                  Zitat von tuxedo Beitrag anzeigen
                  Andere Domain könnte Problematisch sein, aber anderer Port? Bei mir funktioniert das bis jetzt ganz gut.
                  Keine Ahnung, da ich das nicht nutzte. Habe aber gerade irgendwo gelesen, das es in Zukunft bei SSE möglich sein sollte Cross-Origin-Requests zu machen. Von daher sind wir damit schonmal "zukunftsfähig".

                  Zitat von tuxedo Beitrag anzeigen
                  Dann vllt. doch lieber "X-CometVisu-Backend-LoginUrl" ??
                  Ist vermutlich Haarspalterei, aber irgendwie passiert unter dieser URL ja mehr als ein reines Login (Login, Session-Erstellung, Konfiguration), von daher würde ich da lieber einen allgemeineren Begriff nutzten.


                  Zitat von tuxedo Beitrag anzeigen
                  Jepp, das seh ich auch wenn ich einen Verbindungabbruch forciere (Netzwerkkabel z.b. raus ziehen). Wenn das Device aber schlafen geht und wieder aufwacht, scheint Android zumindest keinerlei anstalten zu machen und einen Verbindungsabbruch mit einer state-änderung zu signalisieren. Der macht einfach gar nix.
                  Also die Änderung des readyState sehe ich hier, wenn Android schlafen geht. Problem ist nur, dass es diese nützliche Information für sich behält, d.h. ich sehe das nur wenn ichs aktiv abfrage es gibt keine error message oder ein sonstiges Event auf das man lauschen könnte.
                  Ich kann mir nur schwer vorstellen, dass es ein zuverlässiges Event gibt, dass beim Aufwachen im Browser gefeuert wird, von daher wird das wohl eher ein Wunschtraum bleiben. Wird wohl auf den Watchdog hinauslaufen.
                  Gruß
                  Tobias

                  Kommentar


                    #10
                    Zitat von peuter Beitrag anzeigen
                    Mit Teil-URL meinte ich, dass man da immer noch den read/write/rrd Pfad dranhängen muss um eine komplette URL zum Backend zu bekommen. Von daher ist es ein prefix. Wie schon vorgeschlagen würde ich das dann baseURL nennen, das suggeriert zumindest aus meiner Sicht nicht, dass man da nicht auch ne absolute URL angeben kann.
                    Ach so... ja klar. Stand etwas auf dem Schlauch. baseURL find ich ein guter kompromiss.


                    Keine Ahnung, da ich das nicht nutzte. Habe aber gerade irgendwo gelesen, das es in Zukunft bei SSE möglich sein sollte Cross-Origin-Requests zu machen. Von daher sind wir damit schonmal "zukunftsfähig".
                    Ist doch super...


                    Ist vermutlich Haarspalterei, aber irgendwie passiert unter dieser URL ja mehr als ein reines Login (Login, Session-Erstellung, Konfiguration), von daher würde ich da lieber einen allgemeineren Begriff nutzten.
                    Na aber es ist doch exakt die Login-URL... Wäre also treffend. Was in tieferen Schichten passiert interessiert ja auf dieser "Konfigurationsebene" nicht.
                    Wenn der Name allgemein gehalten wird, aber zwangsweise auf ein get an diese Adresse ein Login-Response kommen soll... Dann leuchtet mir nicht ein warum das nicht login-url (öder ähnlich) heissen soll, sondern eher allgemein gehalten wird.

                    Aber auf der anderen Seite bekommen die meisten Anwender das überhaupt nicht mit.


                    Also die Änderung des readyState sehe ich hier, wenn Android schlafen geht. Problem ist nur, dass es diese nützliche Information für sich behält, d.h. ich sehe das nur wenn ichs aktiv abfrage es gibt keine error message oder ein sonstiges Event auf das man lauschen könnte.
                    Ah, ok, dann haben wir aneinander vorbei geredet. Ich habs nicht aktiv abgefragt. Aber vielleicht könnte man das in einem nebenläufigen Thread? Dann kann man sich ein KeepAlive sparen und muss lediglich die state-Variable überwachen. Klingt gut.

                    Kommentar


                      #11
                      Zitat von tuxedo Beitrag anzeigen
                      Na aber es ist doch exakt die Login-URL... Wäre also treffend. Was in tieferen Schichten passiert interessiert ja auf dieser "Konfigurationsebene" nicht.
                      Wenn der Name allgemein gehalten wird, aber zwangsweise auf ein get an diese Adresse ein Login-Response kommen soll... Dann leuchtet mir nicht ein warum das nicht login-url (öder ähnlich) heissen soll, sondern eher allgemein gehalten wird.
                      Wie gesagt "Haarspalterei" und nicht weiter relevant. Da es auf CometVisu-Seite Login heißt (obwohl ichs anders nennen würde ;-), sollten wir den Header auch so benennen um eventuelle Mißverständnisse, zu vermeiden hast mich überzeugt.

                      Ich habe mal einen rudimentären watchdog für SSE eingebaut, der einfach alle 5 Sekunden prüft ob die SSE Verbindung noch da ist und ggf. neu verbindet. Das sollte der Browser mit SSE zwar laut beschreibung alles selbst und automagisch können, aber die Realität sieht hier offensichtlich mal wieder anders aus.
                      Teste das bitte mal, ich habs nur rudimentär getestet, vor allem wäre es interessant wie sich das Ding bei längerer Laufzeit verhält.

                      PS:
                      Weitere Ändeurngen wir "X-CometVisu-Backend-LoginUrl" Umbenennung mache ich morgen (hoffentlich)
                      Gruß
                      Tobias

                      Kommentar


                        #12
                        Ich schau mal ob ich morgen zum einspielen der Änderung und testen komme.

                        (obwohl ichs anders nennen würde ;-)
                        ich glaub ich weiß woher der Wind weht: Der Login ist kein richtiger Login, obwohl er mal dafür gedacht war. Stattdessen mutiert's gerade etwas zu einer Art Setup-URL oder so.

                        Langfristig würde ich aber schon schauen ob man nicht doch den Login im Backend und auch im Frontend weiter implementiert.

                        Kommentar


                          #13
                          Bin gerade am testen.

                          Zwei Dinge:

                          1) Mein Header sieht so aus:

                          Code:
                          X-CometVisu-Backend-LoginUrl:http://192.168.200.69:8080/kad/l
                          X-CometVisu-Backend-Name:KnxAutomationDaemon
                          CV macht daraus dann diesen Request:

                          Man beachte den zusätzlichen Slash... Ist das so gewollt?

                          2) Hattest recht mit dem CrossSite Request. Mein Chrome sagt mir:

                          No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.200.69' is therefore not allowed access.
                          Hatte wohl vergessen dass ich nur das einsetzen meines Headers getestet, den tatsächlichen CrossSite Request aber nicht mehr getestet habe.

                          Ich werde mal schauen ob ich den "geforderten" Header eintragen kann. Ansonsten halt doch mod-proxy

                          [update]
                          Wenn ich vorrübergehend mod-proxy einsetze geht's ein stückchen weiter.D.h. der Login-URL Aufruf klappt. Aber alle weiteren Requests gehen an die falsche Adresse:

                          http://192.168.200.69/cgi-bin/r?s=23823192-d17d-4138-b.......

                          Muss ich mich mal genauer mit beschäftigen....


                          [update]
                          Ah, jetzt ...
                          der Login-Response wird wohl noch gar nicht ausgewertet. Hatte das schon mal vorbereitet:

                          https://github.com/tuxedo0801/CometV...rsal-client.js

                          [
                          update]
                          Ich hab blödsinn erzählt. Wird ausgewertet, aber funktioniert wieso auch immer nicht. *debuggengeh*
                          Zuletzt geändert von tuxedo; 19.11.2015, 17:50.

                          Kommentar


                            #14
                            Zitat von tuxedo Beitrag anzeigen
                            Man beachte den zusätzlichen Slash... Ist das so gewollt?
                            Gewollt war der, nur nicht an der Stelle. Der sollten an die baseURL (aka urlPrefix). Ist gefixt und die Umbenennung von urlPrefix nach baseURL ist auch mit drin.

                            Zitat von tuxedo Beitrag anzeigen
                            der Login-Response wird wohl noch gar nicht ausgewertet. Hatte das schon mal vorbereitet:
                            Doch wird er, sonst würde es bei mir ja nicht funktionieren. Was gibt denn Dein Login genau zurück, kannst Du mal die JSON Antwoert vom backend posten?
                            Die Auswertung findet hier statt:
                            https://github.com/peuter/CometVisu/...client.js#L185

                            Da werden die Default Config Werte mit denen vom Backend überschrieben.
                            Gruß
                            Tobias

                            Kommentar


                              #15
                              Ich sehe schon an Deiner Auswertung das Du vermutlich den baseURL Parameter nicht sendest (bzw. früher halt urlPrefix) und dann nimmt er halt den default Wert '/cgi-bin/'
                              Gruß
                              Tobias

                              Kommentar

                              Lädt...
                              X