Ankündigung

Einklappen
Keine Ankündigung bisher.

Kompatibilität von Edomi mit neueren PHP Versionen

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

    Kompatibilität von Edomi mit neueren PHP Versionen

    Hallo zusammen,

    auch auf die Gefahr hin gesteinigt zu werden, möchte ich dennoch gerne die Frage an Christian richten, ob und wann der Edomi-Code auch für aktuelle(re) PHP-Versionen lauffähig ist bzw. sein wird.

    Hintergrund ist, dass ich heute mit einem LBS für einen MQTT-Client anfangen wollte, der einen PHP-Wrapper für die libmosquitto benutzen sollte.
    Leider arbeitet dieser Wrapper nur mit neueren PHP-Versionen vernünftig zusammen. Bei der PHP-Version 5.3.3 von CentOS 6.5 sind zwei Patches notwendig, damit der Code überhaupt baut. Allerdings schlägt "make test" danach bei vielen Test fehl.

    Natürlich kann ich auch eine andere PHP-Klasse für den MQTT-Client nehmen wie z.B. diese hier....



    #2
    Zitat von Nanosonde Beitrag anzeigen
    Hallo zusammen,

    auch auf die Gefahr hin gesteinigt zu werden, möchte ich dennoch gerne die Frage an Christian richten, ob und wann der Edomi-Code auch für aktuelle(re) PHP-Versionen lauffähig ist bzw. sein wird.

    Hintergrund ist, dass ich heute mit einem LBS für einen MQTT-Client anfangen wollte, der einen PHP-Wrapper für die libmosquitto benutzen sollte.
    Leider arbeitet dieser Wrapper nur mit neueren PHP-Versionen vernünftig zusammen. Bei der PHP-Version 5.3.3 von CentOS 6.5 sind zwei Patches notwendig, damit der Code überhaupt baut. Allerdings schlägt "make test" danach bei vielen Test fehl.

    Natürlich kann ich auch eine andere PHP-Klasse für den MQTT-Client nehmen wie z.B. diese hier....

    Teile von EDOMI sind mit bcompiler compiliert. bcompiler ist nur bis PHP 5.3.x lauffähig. Daher ist derzeit keine Änderung in Sicht.

    Kommentar


      #3
      Aus einer ähnlichen Frage habe ich vor ein paar Tagen (zum Thema Multicast) aber mitgenommen: Man könnte eine aktuelle PHP-Version parallel installieren und außerhalb von edomi auch ausführen - die Herausforderung wäre eine charmante Interaktion von EXCE-Teil (in 5.x) in edomi und den Teilen "draußen": DB, Dateien,...

      Vielleicht eine Idee? Oder liege ich mit meinem Verständnis des letzten Themas dazu falsch? Nicht optimal, aber ich fänd's für mich völlig okay, wenn ich aktuell nicht schon genug Aufgabe in edomi hätte, die meine Zeit binden...
      Zuletzt geändert von saegefisch; 18.10.2016, 18:56.

      Kommentar


        #4
        ja, das stimmt. Außerhalb eines LBS ist alles möglich. Auch PHP 7.x.

        Kommentar


          #5
          Zitat von saegefisch Beitrag anzeigen
          A[...]die Herausforderung wäre eine charmante Interaktion von EXCE-Teil (in 5.x) in edomi und den Teilen "draußen": DB, Dateien,...

          Vielleicht eine Idee? [...]
          Genau darüber habe ich auch schon nachgedacht.
          Um den Teil innerhalb des LBS so einfach und schlank wie möglich zu halten, würde ich gerne die Repräsentation des LBS mit seinen Ein- und Ausgängen "nach außen verlagern". Die andere Richtung wäre es z.B. mittels RPC Methoden, Daten von externen PHP libs, etc. "hereinzuholen". Dies würde ich allerdings vermeiden, um den Ballast innerhalb des LBS so klein wie möglich und so einfach wie möglich zu halten.

          Der Exec-Teil des LBS soll als Daemon die Verbindung zur eigentlichen LBS-Intelligenz, die extern implementiert ist (ggf. auch in einer anderen Sprache) halten und für die bidirektionale Kommunkation sorgen.
          Die externe LBS-Intelligenz soll quasi die gleiche API nutzen können, wie sie innerhalb des LBS im Exec-Teil oder im LBS-Abschnitt zur Verfügung steht.
          Die wenigen API-Aufrufe könnten dann z.B. über Sockets in Form von einfachem RPC abgebildet werden.

          Folgende Schwierigkeit sehe ich allerdings:
          Es soll ja alles möglichst schön asynchron Event-gesteuert ohne Polling ablaufen. Wie mache ich das mit der Benachrichtigung der externen LBS-Intelligenz, wenn ein Eingang getriggert wird? Der Code im LBS-Abschnitt kann dem Code im Exec-Abschnitt ja nichts mitteilen. Im Exec-Abschnitt funktioniert die "refresh"-Eigenschaft nicht zuverlässig laut Hilfe. Nur die "value"-Eigenschaft ist aktuell. Unschön wäre, wenn man im Exec-Teil alle Eingänge permanent pollt, um eine Änderung zu detektieren und damit die Benachrichtigung auslösen zu können.
          Die Herausforderung wäre hier eine Lösung in Form von Code für den LBS-Abschnitt zu finden, der der externen LBS-Intelligenz die Benachrichtigung zukommen lässt, ohne großartig Zeit dafür zu benötigen, da der LBS-Abschnitt ja im Kontext der Logik-Engine ausgeführt wird.
          Eine mögliche Lösung wäre hier evtl. auch eine Socket-Verbindung als Datagramm per UDP.

          So gäbe es dann insgesamt eine bidirektionale TCP-Verbindung für die API per RPC und eine unidirektionale Verbindung per UDP von EDOMI LBS zur externen LBS-Intelligenz: TCP im Exec-Teil und UDP im LBS-Teil

          Diese ganze Geschichte wäre dann so allgemein, dass ein LBS in verschiedenen Sprachen extern aufgebaut werden könnte.

          Mal weiter gesponnen könnte der LBS auch ein Stück echte HW mit Netzwerkzugang sein, die die oben beschriebene EDOMI-LBS TCP/UDP Kombo spricht.
          (Ein LBS Eingang wäre z.B. ein echter Eingang an einem Arduino oder so).
          Zuletzt geändert von Nanosonde; 19.10.2016, 12:04.

          Kommentar


            #6
            Vielleicht reicht es auch weniger kompliziert, indem einfach nur sichgerstellt ist, dass die aktuellen Eingangswerte bei der externen LBS-Intelligenz vorliegen.
            An mehr ist man doch eigentlich nicht interessiert oder? Dann könnte man die Abbildung der LBS-API als RPC einsparen.
            Wenn dann noch die Benachrichtigung über die Änderung an einem Eingangswert vorhanden ist, sollte das doch reichen.

            Noch eine andere Überlegung zum Thema Sockets: Könnte das Exec-Skript nicht einen Socket öffnen und den Socket-Deskriptor als LBS-Variable speichern, so dass im LBS-Abschnitt mit Hilfe dieses Deskriptors ein socket_write() möglich wäre? So könnte man die UDP-Verbindung einsparen.
            Vermutlich geht das nicht, weil es unterschiedliche Prozesse sind, richtig?

            UPDATE:
            Ich sehe gerade, dass jonofe die Kommunikation zwischen LBS- und EXEC-Teil mittels Message Queue abwickelt. LINK
            Dann gäbe es ja dieses Thema auch nicht mehr.

            Es wäre echt prima, wenn es so eine Art LBS-SDK für externe LBS-Bausteine gäbe. Der LBS-Baustein, der in EDOMI geladen wird, sieht - bis auf die Anzahl der Ein- und Ausgänge und den Hilfetext - immer gleich aus: LBS-Teil kommuniziert mit EXEC-Teil, der wiederrum die Kommunikation mit dem LBS-SDK im externen Programm gewährleistet.

            UPDATE2:
            Ich zitiere mal einen Satz, den ich gerade hier gelesen habe:
            PHP's native message queue works by storing messages in shared memory, and is accessible to other processes on your machine. In PHP's words, "They provide a simple and effective means of exchanging data between processes." If I was developing a large, enterprise message queue, I would not use these functions, as they don't allow workers and job servers to be managed across multiple servers. For smaller projects and tinkering around, PHP's functions are a great way to understand how message queues work and to process a small amount of requests.
            Ich denke also, dass Message Queues in diesem Fall eine völlig legitime Wahl des Mittels darstellt. Vor allem, da intern auch shared memory benutzt wird, ich mich aber nicht selbst um Race Conditions, etc. kümmern muss. Ich beziehe mich hier auf die Aussage von gaert.
            Zuletzt geändert von Nanosonde; 19.10.2016, 12:43.

            Kommentar


              #7
              Ich habe schon seit einiger Zeit so etwas auf meiner ToDo Liste stehen. Und zwar ziemlich genau so, wie Du es beschrieben hast.

              Idee: Einen Kommunikationsbaustein, der die Daten mit externen LBS über Message Queues austauscht, die ja eigentlich in allen höheren Programmiersprachen irgendwie ralisiert sind. Dieser Baustein hat dann z.B. 10 Eingänge und 10 Ausgänge udn könnte somit 10 externe LBS unterstützen.

              Dazu dann ein generischer EDOMI LBS mit Eingängen und Ausgängen. Dieser ist dann quasi der virtuelle LBS zu dem LBS, der z.B. in Java, PHP7 oder C# realisert ist. Die Eingänge des virtuellen LBS werden dann zusammen mit den Variablen (#v) über einen Ausgang zusammengefasst und an den Kommunikationsbaustein geschickt. Dieser sendet die Daten dann via Message Queue an den externen LBS. Dieser sendet dann Ausgänge, Variablen-Updates, Logging via Message Queue zurück an den Kommunikations LBS, der dann die Daten azusammenfasst und über einen Ausgang an den virtuellen LBS sendet. Dieser kann dann die Ausgänge und Variablen setzen.

              Ich habe dazu schon mal ein Bild gemacht (hand gekritzelt) welches ich später mal hochladen kann.
              Zur Kommunikation mit dem externen LBS benötigt der virtuelle LBS dann nur einen Ausgang und einen Eingang. Weitere Eingänge und Ausgänge sind dann die Ein/Ausgänge des eigentlichen LBS.

              Macht das Sinn?

              VG

              André

              Kommentar


                #8
                Klingt spannend... d.h. man könnte dann auch externe Funktionen leichter nutzen und müsste diese nicht mühsam versuchen in LBS-Struktur zu pressen, z.B. das: https://duncan3dc.github.io/sonos/ ?

                Kommentar


                  #9
                  Hier mal die Skizze zu meinen weiter oben beschriebenen Gedanken:

                  EDOMI-external-LBS.png

                  Oben die virtuellen LBS, die je einen externen LBS repräsentieren. Über einen Eingang bekommen diese die Updates vom externen LBS via Message Queue LBS.
                  Über einen Ausgang senden die virtuellen LBS Änderungen an ihren Inputs via Message Queue LBS zum externen LBS. Ein Message Queue LBS unterstützt dabei 10 externe LBS. Alle kommunizieren über dieselbe Message Queue mit unterschiedlichen Message Typen. Die externen LBS können dann in verschiedenen Sprachen realisiert sein.

                  Ich habe heute Abend mal eine erste quick&dirty Version implementiert, um testen zu können, wie die Performance ist.

                  Hier mal ein Screenshot:

                  externe LBS.png

                  Oben der Message Queue LBS, den man mit einer Message Queue ID und einem LogLevel konfiguriert. Zusätzlich hat er 10 Eingänge und 10 Ausgänge für die max. 10 virtuellen LBS. Unten drei virtuelle LBS, denen man einen Namen geben kann und denen man eine ID zuweist (1-10). Die ID entspricht dann der LBS Nummer im Message Queue LBS. Jeder virtuelle LBS hat 10 Eingänge und 10 Ausgänge, die man quasi frei verwenden kann. Die 10 Eingänge werden an den externen LBS weitergeleitet. Den Eingang E2 (Input) verbindet man mit dem entsprechenden Ausgang des Message Queue LBS, d.h. Ausgang "Out - LBS 1" des Message Queue LBS wird mit dem Eingang E2 "Input" des virtuellen LBS mit der ID 1 verbunden. Außerdem wird der "Output" Ausgang A1 des virtuellen LBS mit dem entsprechenden "In LBS #" Eingang des Message Queue LBS verbunden. Bsp.: "Output" von Virtual LBS 1 auf "In LBS 1" des Message Queue LBS. Das wars dann schon.

                  Ändert sich nun ein Eingang (E5-E14) des virtuellen LBS1, dann wird dies über den Output Ausgang A1 an den Message Queue LBS weitergegeben. Dieser schreibt es in die Message Queue, die der externe LBS dann ausliest. Dazu muss der externe LBS dieselbe Message Queue ID verwenden, die auch der Message Queue LBS verwendet (E1). Wenn es der externe LBS1 ist, dann liest dieser die Messages vom Typ "Message Queue ID + 1" aus. Der externe LBS3 würde sich mit derselben Message Queue ID verbinden, aber Messages des Type "Message Queue ID + 3" auslesen.

                  Die Kommunikation vom externen LBS erfolgt dann über ein Array mit der Struktur

                  PHP-Code:
                  array( => LBSID,
                  => 'Wert für Ausgang 1',
                  => 'Wert für Ausgang 2',
                  => 'Wert für Ausgang 3',
                  => 'Wert für Ausgang 4',
                  => 'Wert für Ausgang 5',
                  => 'Wert für Ausgang 6',
                  => 'Wert für Ausgang 7',
                  => 'Wert für Ausgang 8',
                  => 'Wert für Ausgang 9',
                  10 => 'Wert für Ausgang 10'
                  ); 
                  Dieses Array wird dann als Message mit dem Typ "Message Queue ID" gesendet. Nur der Message Queue LBS nimmt Nachrichten dieses Typs aus der Queue und leitet diese an die virtuellen LBS weiter.

                  Ich habe dies kurz mit folgendem Skript getestet:

                  PHP-Code:
                  <?php
                  $msgQID 
                  1001;
                  $msg_queue msg_get_queue($msgQID);

                  while (
                  1) {
                      
                  // Receive Outputs from external LBS (MSG Type = 2) ***blocking***
                      
                  if (msg_receive($msg_queue0$msgtype4096$Etrue0$msg_error)) {
                          
                  $virtLBSId $E[3]['value'];
                          echo 
                  "Received MSG_TYPE: " $msgtype "\n";
                          
                  $outputdata = array(
                              
                  => $virtLBSId,
                              
                  => 'Out1 (' $msgtype ')',
                              
                  => 'Out2 (' $msgtype ')',
                              
                  => 'Out3 (' $msgtype ')',
                              
                  => 'Out4 (' $msgtype ')',
                              
                  => 'Out5 (' $msgtype ')',
                              
                  => 'Out6 (' $msgtype ')',
                              
                  => 'Out7 (' $msgtype ')',
                              
                  => 'Out8 (' $msgtype ')',
                              
                  => 'Out9 (' $msgtype ')',
                              
                  10 => 'Out10 (' $msgtype ')'
                          
                  );
                          
                  msg_send($msg_queue$msgQID$outputdata);
                          
                  print_r($outputdata);
                      }
                      
                  usleep(10000);
                  }

                  ?>
                  Das Skript gibt dann jeweils das Array der Eingänge des virtuellen LBS aus, sobald sich bei diesem etwas auf den Eingängen E5-E14 tut. Danach sendet er Testdaten für alle 10 Ausgänge zurück. Diese erscheinen dann in der Liveansicht in EDOMI.

                  Werde die Bausteine morgen mal hochladen. Wie gesagt, sind sie erst heute Abend entstanden und ob es wirklich so mit externen LBS funktioniert, muss ich mal testen. Ggf. wäre eine Alternative je externem LBS eine eigene Message Queue zu verwenden. Dazu würde man dann die Ein-/Ausgänge des virtuellen LBS in den Message Queue LBS verschieben und je einen Message-Queue-LBS pro externem LBS verwenden.

                  Und damit sag ich jetzt Gute Nacht

                  André

                  Kommentar


                    #10
                    Okay, alles zurück ... mit einem LBS je externem LBS ist doch viel besser:

                    externerLBS.png

                    Nur ne Message Queue ID und den Loglevel und dann x Eingängen und y Ausgänge (hier jeweils 10).
                    Bei Änderung eines Eingangs werden die Eingänge in die Message Queue geschrieben (Message Type 1) und beim Empfang von Daten vom externen LBS (Message Type 2) werden diese auf die y Ausgänge geschrieben.

                    Hier noch das Skript zum Testen:

                    PHP-Code:
                    <?php
                    $msgQID 
                    1002;
                    $msg_queue msg_get_queue($msgQID);

                    while (
                    1) {
                        
                    // Receive Outputs from external LBS (MSG Type = 2) ***blocking***
                        
                    if (msg_receive($msg_queue1$msgtype4096$Etrue0$msg_error)) {
                            
                    print_r($E);
                            
                    $outputdata = array(
                                
                    => 'Out1 (' $msgtype ')',
                                
                    => 'Out2 (' $msgtype ')',
                                
                    => 'Out3 (' $msgtype ')',
                                
                    => 'Out4 (' $msgtype ')',
                                
                    => 'Out5 (' $msgtype ')',
                                
                    => 'Out6 (' $msgtype ')',
                                
                    => 'Out7 (' $msgtype ')',
                                
                    => 'Out8 (' $msgtype ')',
                                
                    => 'Out9 (' $msgtype ')',
                                
                    10 => 'Out10 (' $msgtype ')'
                            
                    );
                            
                    msg_send($msg_queue2$outputdata);
                        }
                        
                    usleep(10000);
                    }

                    ?>
                    Das Skript gibt die Eingangswerte aus und sendet 10 Ausgangswerte zurück.

                    Wie ich finde viel einfacher und effizienter und je externem LBS genau ein EDOMI LBS.

                    Gute Nacht ....

                    André

                    Kommentar


                      #11
                      Wow, André!
                      das hört sich doch schon ziemlich nach "charmante Interaktion" ohne viel blingbling an; wenn das funktioniert, sieht es eher wunderbar schlank aus. Und die Verwendung je eines edomi LBS zu jedem externen LBS hört sich auch logischer und leichter nachvollziehbar an. Beeindruckend, danke für Deinen Einblick. Wenn diese "middle-ware" nun auch performance-mäßig unauffällig bleibt beim "listening" sieht das nach einem "Schweizer Messer" für besondere Anforderungen aus.

                      Viele Grüße und schöne Träume (gehabt zu haben),
                      Carsten

                      Kommentar


                        #12
                        Ich habe jetzt mal den oben beschriebenen LBS hochgeladen:
                        Auf E1 gibt man dem externen LBS eine Namen. Dies wird lediglich für den Namen des Logfile verwendet.
                        E2 ist die Message Queue ID. Diese kann frei gewählt werden und muss vom Typ Interger sein. Diese ID muss auch im externen LBS verwendet werden, um zur Message Queue zu connecten.
                        E3 konfiguriert den Loglevel (0-8)
                        E4/E5 gibt die Anzahl der Ein-/Ausgänge an. Wenn mehr als 10 benötigt werden, einfach diese Zahl erhöhen und im LBS ###[DEF]### Source-Code einfach Ein-/Ausgänge hinzufügen. Ansonsten ist keine Anpassung im Source-Code notwendig. Auf gleiche Weise kann natürlich auch die Anzahl der Ein-/Ausgänge reduziert werden. Anzahl der Ein-/Asugänge kann unterschiedlich sein. (z.B. 10 Eingängen / 5 Ausgänge)

                        Ein eintreffendes Signal an E6-E15 triggert den LBS und sendet die $E[6] bis $E[15] als JSON encodeten String via Message Queue an den externen LBS (z.B. PHP7 oder JAVA Skript). Dieser muss es JSON decoden und kann die Werte entsprechend verwenden.

                        Der externe LBS hat nun die Möglichkeit Ausgänge des External-LBS-Connectors zu ändern. Dazu sendet er auch einen JSON encodeten String per Message Queue zurück. Hier stehen 3 Optionen zur Verfügung:

                        1.) Beispiel: Setzen der Ausgänge 1,3,5,10 via logic_setOutput:

                        Code:
                            {"0":"[COLOR=#FF0000]Output[/COLOR]","1":"[COLOR=#0000CD]Value Output 1[/COLOR]","3":"[COLOR=#0000CD]Value Output 3[/COLOR]","5":"[COLOR=#0000CD]Value Output 5[/COLOR]","10":"[COLOR=#0000CD]Value Output 10[/COLOR]"}
                        2.) Beispiel: Setzen der Ausgänge 1,4,6,8 via logic_setOutputQueued():

                        Code:
                            {"0":"[COLOR=#FF0000]OutputQueued[/COLOR]","1":"[COLOR=#0000CD]Value Output 1[/COLOR]","4":"[COLOR=#0000CD]Value Output 4[/COLOR]","6":"[COLOR=#0000CD]Value Output 6[/COLOR]","8":"[COLOR=#0000CD]Value Output 8[/COLOR]"}
                        3.) Beispiel: Senden einer Logging Nachricht (Diese wird im Custom Log File des External LBS Connector LBS geloggt):

                        Code:
                            {"0":"[COLOR=#FF0000]Logging[/COLOR]","1":"[COLOR=#0000CD]<zu loggender Text>[/COLOR]","2":"[COLOR=#0000CD]<loglevel>[/COLOR]"}
                        Zur Nutzung der Message Queue sind folgende Dinge zu beachten:
                        1. Der externe LBS muss dieselbe Message Queue ID (E2) verwenden wie dieser External LBS Connector
                        2. Vom External LBS Connector zum Externen LBS wird Message Type "1" verwendet
                        3. Vom Externen LBS zum External LBS Connector wird Message Type "2" verwendet
                        4. Die Messaged (Eingänge, Ausgänge, Logging) werden JSON encoded/serialisiert und müssen nach dem Empfang entsprechen decoded werden.

                        Ich werde mal einen Test mit einem PHP 5.6.27 basierten LBS machen und wieder berichten, falls es jemanden interessiert. Einen kurzen Test mit einem kleines JAVA und C Programm habe ich heute auch schon gemacht. Aber die Tücken liegen ja meist im Detail, wenn es dann um echte Funktionalität geht.

                        Wenn also Bedarf vorhanden ist, einfach mal testen ....

                        VG
                        André

                        Kommentar


                          #13
                          falls es jemanden interessiert



                          Hätte ich nur mehr Zeit...<grrr>...Wenn das Projekt beim Kunden von meinem geplanten Urlaub kommende Woche wenigstens die Hälfte übrig lässt, würde ich mal das Multicast-Thema aus dem anderen Threat mit aktuellem PHP versuchen: https://knx-user-forum.de/forum/proj...693#post996693

                          Andere Fragestellungen abseits des Standards hätt' ich gerade nicht. Und wo es nicht nötig ist, würde ich persönlich lieber immer beim Standard bleiben. Aber in den letzten Monaten gab es ja immer mal wieder Themen, wo dies eine Antwort sein würde; daher werden sicher andere folgen...
                          ...wie gesagt...Schweizer Messer...hat MacGuyver es ja auch nur benutzt, wenn es nötig war. Aber dann war es nötig und war auch die Lösung...
                          Zuletzt geändert von saegefisch; 20.10.2016, 23:31.

                          Kommentar


                            #14
                            Ich versteh den ganzen Aufwand nicht...
                            Seit nunmehr 7 Monaten gibt es meinen brainf*ck-Interpreter-Baustein. Damit kann man doch alles erschlagen was in PHP nicht geht

                            Kommentar


                              #15
                              Ja das sehe ich auch so. Ist für mich auch im Moment mehr eine technische Spielerei. Habe heute mal phpbrew ausprobiert. Damit kann man auf sehr einfache Weise verschiedene PHP Versionen installieren und parallel nutzen. Man kann sie ganz einfach umschalten und dann nutzen. Zusammen mit diesem LBS mal eine Möglichkeit etwas zu spielen.

                              Du hast Recht, das multicast Thema wäre vielleicht mal ein guter PoC...

                              Kommentar

                              Lädt...
                              X