Ankündigung

Einklappen
Keine Ankündigung bisher.

Logikengine, java powered

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

    #16
    Hallo Alex,

    ich lese hier schon von Anfang an interessiert mit, habe aber nicht die Zeit gefunden, zu Antworten.
    Ich muss ehrlich sagen, dass ich die Entscheidung gegen etwas existierendes und für etwas neues recht 'hoppladihop' fand. Aber das sei dir zugestanden. Ich hätte mich allerdings gefreut, wenn deine Programmierstunden sh.py zu Gute gekommen wären. Aber das ist purer Egoismus meinerseits.

    Was mich interessiert ist der Export der GAs. Das Anlegen der Items nervt mich bei Sh.py doch noch sehr. Es gibt auch da einen Ansatz für einen Export aus der ETS, der ist aber für mich auch nicht praktikabel. Das Problem ist, dass bei vielen GAs der DPT anscheinend nicht mit gespeichert wird.
    Links:
    https://knx-user-forum.de/forum/supp...er-ets4-import
    https://knx-user-forum.de/forum/supp...her-ets-import

    Zitat von tuxedo Beitrag anzeigen
    - Einlesen der knxproj-Datei die man mit ETS exportiert hat --> Damit hat man Gruppenadressen und zugehörige DPTs, soweit aus dem KNX Projekt überhaupt herauslesbar (da geh ich gleich nochmal genauer darauf ein...)
    Das hast du wohl vergessen ;-)
    Bist du zufrieden mit dem Export der GAs inklusive DPT?

    Gruß,
    Hendrik

    Kommentar


      #17
      Ich muss ehrlich sagen, dass ich die Entscheidung gegen etwas existierendes und für etwas neues recht 'hoppladihop' fand.
      Das denk' ich mir.

      Aber das sei dir zugestanden. Ich hätte mich allerdings gefreut, wenn deine Programmierstunden sh.py zu Gute gekommen wären.
      Mit Python hab ich's nicht so. Ich komm damit zurecht, aber "meine Sprache" ist das leider nicht.

      Was mich interessiert ist der Export der GAs.
      Wenn du jetzt genauer ins Detail gegangen wärst, hätte ich vielleicht nicht so viel schreiben müssen. Aber so hole ich jetzt ein klein wenig aus:

      Ich entpacke die .knxproj Datei und parse den Inhalt. Das geschieht direkt bei Programmstart. Ich konvertiere nichts und schreibe damit keine Konfig. Ich biete lediglich über die API den Zugriff auf die GA's mit dem Namen den man in der ETS vergeben hat an. Dazu kann man noch die DPT der jeweiligen GA erfragen.

      Bei dern DPTs gibt's zwei Möglichkeiten:

      Entweder die GA hat schon einen DPT zugeordnet, oder eben nicht.

      Falls nicht, schaut meine Implementierung nach den verknüpften KOs und welches Gerät da dahinter steckt. Da kann man dann weiter nachschlagen welches KO das genau ist und was das für ein DPT hat.

      Sobald eine GA in ETS also mit einem KO eines Geräts verknüpft ist, habe ich ziemlich sicher auch ein DPT dazu.

      Funktioniert bisher recht gut.
      Die Idee mit der Interface-Generierung für die GAs habe ich noch nicht umgesetzt. Steht aber fest auf dem Plan. Denn damit hat man, spätestens wenn man eine IDE benutzt, eine Auto-Vervollständigung bei der Verwendung der GA in Logiken etc.

      Wenn ich mal soweit bin, kann man da noch ein bisschen was drum rum bauen um das als Konverter zu benutzen und direkt von der Konsole aus aufzurufen. Dann könnte man es auch für andere Projekte (SH) verwenden/einbauen.

      Die letzten Tage habe ich damit verbracht das Scripting von Beanshell auf echtes Java umzustellen. Der erste Prototyp hat funktioniert und ist bereits in die Logikengine eingebaut. Muss aber damit noch getestet werden. Aber ich bin zuversichtlich.
      Geplant ist, dass die Scripts nicht allein in den Heap kompiliert werden, sondern tatsächlich als Class-Files auf der Platte landen. Beim erneuten Start wird dann per Prüfsumme kontrolliert ob sich an den Scripts etwas geändert hat und ob ein Script erneut compiliert werden muss. Das spart Zeit beim Start.

      Wo ich mir noch nicht sicher bin ob ich da Zeit reinstecken soll ist das laden/entladen von Scripts zur Laufzeit. Mal sehen. Das wird sich auch ohne weiteres später noch realisieren lassen.

      Jetzt muss erstmal das Grundgerüst sauber laufen und sich im Alltag bewähren.

      Kommentar


        #18
        Mal wieder ein kleines, aber diesmal etwas genervtes Update:


        Ich dachte ich fahre ganz gut wenn ich alles auf OSGI aufbaue. Damit spare ich mir das basteln einer eigenen Plugin-Logik und ich könnte das ganze recht einfach durch weitere Features erweitern.

        Pustekuchen: Das Laufzeitkompileiren der Scripts im zusammenhang mit OSGI macht mir da gerade einen Strich durch die Rechnung:

        Ohne OSGI funktioniert das prima. Mit findet er während dem compilieren die abhängigkeiten nicht, obwohl ich ihm einen Classloader an die Hand gebe der die Klassen laden können sollte.

        Mal schauen wie ich weiter mache. Ggf. dann halt ohne das Monster OSGI. Manchmal ist Plain-Old-Java-Style eben das beste...

        Kommentar


          #19
          Nach dem Stress mit dem Classloader funktioniert es nun endlich.

          Von OSGI bin ich wieder etwas abgekommen (auch wenn es damit prinzipiell auch funktionieren sollte). Grund:

          1) Die jetzige Lösung ist kleiner: Weniger Kilobytes und weniger Klassen die man laden muss (ich denke da immer an Raspi und dergleichen) --> Schnellere Startup-Zeit
          2) Weniger Code-Overhead: Minimum 600kb komprimiertes Framework vs. aktuell max. 55 kbyte Plugin-Framework (https://github.com/decebals/pf4j). Im Ernstfall kann man das noch ohne weiteres debuggen. Bei OSGI wird es da deutlich komplexer.


          Der Laufzeit-Compiler läuft als separates Unterprojekt. Was das Hauptprojekt jetzt noch braucht ist ein include/lib/"fertige Module" Ordner in den man fertige Logikbausteine/Methoden stecken und von den Scripts aus nutzen kann (Sonnenstandsberechung, Verschattungssteuerung, ...). Eben ähnlich wie im HS mit den vorhandenen Bausteinen die man dann selbst "kombinieren" kann.
          Sollte jetzt aber kein großes Ding mehr sein.

          Denke in 1-2 Wochen kann ich die erste Alpha präsentieren.
          Zuletzt geändert von tuxedo; 02.09.2015, 15:34.

          Kommentar


            #20
            Bin nebenbei dran die Logik-Schnittstelle zu vereinfachen. Hier wieder mein Musterbeispiel

            Code:
            package de.mylogic;
            
            import de.root1.slicknx.GroupAddressEvent;
            import de.root1.kad.logicplugin.Logic;
            import de.root1.slicknx.KnxException;
            
            public class LichtAutoAusBadEG extends Logic {
            
                String gaLichtBad = getGA("Licht Raumschaltung Bad EG");
                String gaPräsenzBad = getGA("Präsenz Bad");
                
                boolean letztePräsenz = false;
                
                @Override
                public void init() {
                    setPA("1.1.100");
                    listenTo(gaPräsenzBad);
                }
                
                @Override
                public void knxEvent(GroupAddressEvent event) {
                        
                        if (letztePräsenz && !event.asBool()) {
                            log.info("");
                            knx.writeBoolean(false /* kein response */, gaLichtBad, false /* Licht aus */);
                        }
                        letztePräsenz = event.asBool();
                                
                }
            
            }
            Ein paar erklärende Worte dazu:

            Für den Nicht-Entwickler sind ggf. "package" und "import" störend. Könnte ich "wegoptimieren" und on-the-fly beim einlesen generieren. Aber ohne das wird der Code nicht mehr in einer "normalen IDE" verwendbar, weil der Compiler im Hintergrund immer motzt dass etwas fehlt.

            "package" kann man selbst frei wählen und sich so von anderen abgrenzen so dass eher weniger ein Namenskonflikt entsteht.

            Den Import-Block... der wird wohl meist aus exakt diesen drei Zeilen bestehen. Aufwendigere Scripts haben dann halt ggf. noch ein paar mehr.

            Die Sache mit dem generierten Interface das die ganzen Gruppenadressen schon als Variable enthält... Hab ich noch nicht umgesetzt. Das würde auch nur dem zum Vorteil sein, der eine IDE benutzt (oder ich muss tatsächlich einen eigenen Editor basteln). Steht bis auf weiteres ganz hinten auf der Liste. Den GA-Namen per Copy&Paste aus einer Textfile zu holen sollte auch weitgehend fehlerfrei möglich sein und nicht sooo viel mehr Zeit in Anspruch nehmen. Die Text-File kann ich noch generieren lassen.

            @Override ... Bläst den Code auch etwas auf, kann aber gefahrlos weggelassen werden. Eine aktuelle IDE baut das aber mit ein.

            Die Methode init() ...
            Hier wird das Script initialisiert. Man kann dem Script eine eigene Physikalische Adresse verpassen (setPA) und die GAs, auf die man lauschen möchte eintragen (listenTo)

            Die Methode knxEvent() ....
            Alle GAs die mit "listenTo" gesetzt wurden können diese Methode auslösen. Und hier kommt ein kleiner Haken: Man muss wissen welche GA welchen Typ hat und dann entsprechend auslesen. 1-Bit Schalt-GAs z.B. kann man mit "asBoolean" lesen.
            Hat man sich hierbei vertan, fliegt einem zur Laufzeit eine Fehlermeldung im Log um die Ohren die hoffentlich recht präzise sagt was nicht geht und wo es nicht geht.

            Soweit irgendwelche Anregungen? Ideen? Kritik?
            Zuletzt geändert von tuxedo; 03.09.2015, 09:57.

            Kommentar


              #21
              Code liegt nun unter GPLv3 bei Github:

              https://github.com/tuxedo0801/KnxAutomationDaemon

              Damit hat das Kind nun auch einen Namen bekommen: "KNX Automation Daemon".

              Der erste Link ist, wie der Name schon verrät, das Compiler für die "Scripts".
              Der zweite Link ist der Daemon selbst: Der besteht aus nur wenigen Zeilen Code und macht eigentlich (zur Zeit) nix anderen wie Plugins zu laden
              Der dritte Link ist das bisher einzige Plugin für den Daemon: Das LogicEngine Plugin.

              Es wird ein weiteres Projekt folgen das alles als "Distribution" zusammenbaut und als ZIP bereitstellt. Sobald das der Fall ist startet die "Alpha-Test-Phase".

              [update]
              Links werden wegen Überarbeitung der Projektstruktur zeitweise nicht gültig sein. Melde mich wenn wieder alles klappt.
              Zuletzt geändert von tuxedo; 08.09.2015, 17:44.

              Kommentar


                #22
                So, die Projektstruktur sollte stehen. Muss noch hier und da was dran basteln und vor allem das Distribution-Projekt dazu bringen ein ZIP zu generieren, aber das sind Details.

                Kommentar


                  #23
                  Hey tuxedo, schön geworden.

                  Stehe eigtl. auch gerade vor Smarthome.py vs. OpenHAB und ein effizientes KNX-only hat was!
                  Sobald ich meinen BBB im Griff habe und die KNX-Installation finalisiert, würde ich auch helfen....

                  Ich lass einfach mal paar Ideen & Gedanken hier...

                  Würde die Scripting-API noch bisschen mehr auf interne DSL trimmen.
                  Als ersten Schritt würde ich versuchen die Java-Bean-Getter wegzuschmeißen & versuchen moderner/natürlicher zu formulieren...
                  Code:
                   
                   log = Logger("Testlogger"); knx = KNX.self("1.1.100"); // KNX.listenTo? KNX.triggerdBy? KNX.reactOn ?
                  Warum benutzt eigentlich getGA nicht das knx-Objekt, wofür ist das überhaupt gut?
                  Hätte etwas Richtung
                  Code:
                  knx.ga()
                  erwartet...

                  Die Idee von bernsen das Interface mit den GAs zu generieren: +1!

                  Ansonsten, warum BeanShell und nicht JavaScript? Da gibts doch Mozilla Rhino für, feine Editoren, language du jour etc. pp.

                  Und "KNX Automation Daemon" ist noch nicht so richtig geil aber habe auch keine besseren Alternativen

                  Kudos für deinen Entwicklungsdruck, da geschieht ja ne ganze Menge

                  Kommentar


                    #24
                    Hallo Alex,

                    ich finde den Ansatz und wie du den Projektverlauf/Gedanken hier dokumentierst toll.

                    Da ich mich aus unterschiedlichen Gründen noch für keine Logik entschieden habe, werde ich mir deine Arbeit auf alle Fälle anschauen auch wenn ich kein Java Fan bin :-)

                    Für mich zählt
                    -Funktion
                    -Zuverlässigkeit
                    -Transparenz

                    Danke gruß Simone

                    Kommentar


                      #25
                      hotzen

                      Würde die Scripting-API noch bisschen mehr auf interne DSL trimmen.
                      Klar, die API lässt sich noch verbessern. erstmal das stabile Grundgerüst, dann die Feinheiten.

                      Code:
                      log = Logger("Testlogger");
                      Klassen schreibt man in Java groß. Folglich ist "= Logger" ein ungültiger Aufruf. Wenn dann "= new Logger" um eine neue Instanz anzulegen, oder "= getLogger()" um einen Logger zu holen.

                      Gerade für Java Einsteiger sind getter ein gutes Konstrukt, finden sich in jeder Java-Doku und sind zudem noch sprechend.

                      Code:
                      knx = KNX.self("1.1.100"); // KNX.listenTo? KNX.triggerdBy? KNX.reactOn ?
                      Wozu direkt ein KNX Objekt ins leben rufen wenn das die Super-Klasse "Logic" bereits macht. Man muss es nur noch "einstellen". setPA folgt zum einen wieder dem Standard der getter/setter die man überall nachlesen kann und die an vielen Ecken und Enden der Java-Welt sich wiederfinden, und zum anderen ist es Sprechend: "set Physical Address". man könnte jetzt noch streiten ob "Physical Address" (wie man es aus der ETS kennt), oder eher "Individual Address" wie es im Standard genannt wird.



                      Warum benutzt eigentlich getGA nicht das knx-Objekt, wofür ist das überhaupt gut?
                      Warum sollte es? Nochmal "knx." davor schreiben bläst den Code nur unnötig auf.
                      Das KNX-Objekt brauchst du um mit dem Bus zu sprechen (read/write). "getGA" selbst: Na zum holen der entsprechenden Gruppenadresse. Sonst müsste man im Script "1/1/123" schreiben. Wenn man in der ETS aber umsortiert, müsste man das Script nochmal anpassen/anpassen. Wenn man den Namen verwendet und diesen in der ETS einmal richtig gesetzt hat, dann funktioniert das Script trotz umsortieren der GAs in der ETS.

                      Die Idee von bernsen das Interface mit den GAs zu generieren: +1!
                      Wie gesagt: Das wird für fortgeschrittene sein die eine IDE verwenden. Steht noch auf der TODO-Liste, aber eher weiter hinten. Mit der String-Basierten referenzierung der GA ist man sowohl mit vi in der Linux-Shell, als auch in der IDE sehr schnell am Ziel. Wenn man das auf Interface-Ebene generiert, dann müssen Leerzeichen und Sonderzeichen entsprechend ersetzt werden. in der IDE ist das mit der Autovervollständigung egal. Da lässt man sich Vorschläge machen und sucht einen aus. In der Shell muss man dann wissen wie der Name der Gruppenadresse umgeformt wurde --> Macht es zumindest für die Shell ein klein wenig komplizierter.

                      Ansonsten, warum BeanShell und nicht JavaScript? Da gibts doch Mozilla Rhino für, feine Editoren, language du jour etc. pp.
                      Du hast den Thread also nur überflogen ;-) Dann ab mit dir und den ganzen Thread lesen. Von Beanshell hab ich mich vor Wochen verabschiedet und setze nun komplett auf Java. Die Scripts werden beim Systemstart on-the-fly zu Java Byte Code compiliert und ausgeführt. Mehr Performance geht nicht.
                      Warum direkt Java? Weil es da am wenigsten Reibungsverluste zwischen Script und eigentlicher Logik-Engine gibt.

                      Und "KNX Automation Daemon" ist noch nicht so richtig geil aber habe auch keine besseren Alternativen
                      Habe lange überlegt und viel Brainstorming betrieben. Aber KNX Automation Daemon (KAD) trifft es am besten. Es ist ein Dienst für die KNX Automatisierung. Die Logik-Engine ist erst der Anfang. In der Planung ist noch eine Datenaufzeichnung sowie eine Schnittstelle zur CometVisu. Meine anderen Projekte (Helios KWL Remote, Modbus2Knx und ekey-decoder) werde ich später auch als Plugin für den KAD auslegen. Dann spart man sich die mehrfachen Java Instanzen wenn man alles einsetzt.

                      @Simone

                      Für mich zählt
                      -Funktion
                      -Zuverlässigkeit
                      -Transparenz
                      Funktion: Für's erste ist es nur die Logik-Engine. Aber wie eben geschrieben ist geplant das ganze Wachsen zu lassen.
                      Zuverlässigkeit: Denke da wird es die wenigsten Schwierigkeiten geben. Wenn sich ein paar Alpha/Beta-Tester finden werden die anfänglichen Kinderkrankheiten sicher schnell gefunden sein. Da ich kein riesen Framework einsetze, ist es auch nicht zu erwarten dass schräge Dinge passieren.
                      Transparenz: OpenSource und eine Doku. hat OpenHAB auch. Aber für meinen Geschmack ist OpenHAB zu einem kleinen Monster gewachsen. Und mit Version 2.0 wird's nicht besser. Aber es verfolgt ja auch eine andere Strategie wie KAD ...

                      Gruß
                      Alex


                      Kommentar


                        #26
                        Hallo Alex,

                        sag Bescheid wenn ich dir bzgl. testen helfen kann.

                        Transparenz: stimme ich dir zu!
                        Die Communnity und Doku von Openhab gefällt mir sehr gut, allerdings ist meine Umgebung aktuell rein auf KNX Basis und wenn es irgendwie geht sollte es so bleiben, deshalb benötige ich das kleine Monster nicht ;-)

                        Eine Datenaufzeichnung sowie eine Schnittstelle zu einer Visu (CometVisu) wäre genial. Kennst du die Qvisu von Max? Hier gibt es ein Sip Anbindung (aktuell für Linux evtl. im Alpha Stadium, näheres kann Max sagen), die würde ich spannend für unsere 2n Türstation finden.

                        gruß simone



                        Kommentar


                          #27
                          Zitat von tuxedo Beitrag anzeigen
                          Code:
                          log = Logger("Testlogger");
                          Klassen schreibt man in Java groß. Folglich ist "= Logger" ein ungültiger Aufruf.
                          Das mit dem groß/klein war mir gar nicht so wichtig (in Scala wäre das übrigens ein gültiger Aufruf vom Companion-Object der Klasse...), wollte darauf hinaus einen Fokus auf natürlichsprachigkeit zu legen und diese elendigen java-bean Getter/Setter zu vermeiden...

                          Zitat von tuxedo Beitrag anzeigen
                          Gerade für Java Einsteiger sind getter ein gutes Konstrukt, finden sich in jeder Java-Doku und sind zudem noch sprechend.
                          Da möche ich dann entschieden widersprechen. Man ist es bei Java-Beans gewöhnt, ja....

                          Zitat von tuxedo Beitrag anzeigen
                          setPA folgt zum einen wieder dem Standard der getter/setter die man überall nachlesen kann und die an vielen Ecken und Enden der Java-Welt sich wiederfinden, und zum anderen ist es Sprechend: "set Physical Address". man könnte jetzt noch streiten ob "Physical Address" (wie man es aus der ETS kennt), oder eher "Individual Address" wie es im Standard genannt wird.
                          Evil Getter/Setter sind kein nachahmenswerter "Standard", das ist, unfair gesagt, altes Bean-Gefrickel. Nicht dass das falsch ankommt, will dir überhaupt nicht den Code zerreden, würde halt nur mehr Augenmerk darauflegen, dass das ganze weniger imperativ (set-PA) wird und mehr deklarativ. Und nein, es ist nicht natürlichsprachig "die Logik auf eine GA zu 'setzen' "

                          Zitat von tuxedo Beitrag anzeigen
                          Du hast den Thread also nur überflogen ;-) Dann ab mit dir und den ganzen Thread lesen. Von Beanshell hab ich mich vor Wochen verabschiedet und setze nun komplett auf Java. Die Scripts werden beim Systemstart on-the-fly zu Java Byte Code compiliert und ausgeführt. Mehr Performance geht nicht.
                          Warum direkt Java? Weil es da am wenigsten Reibungsverluste zwischen Script und eigentlicher Logik-Engine gibt.
                          Schande auf mein Haupt, ja. Sehr gute Idee!

                          Zitat von tuxedo Beitrag anzeigen
                          Habe lange überlegt und viel Brainstorming betrieben. Aber KNX Automation Daemon (KAD) trifft es am besten. Es ist ein Dienst für die KNX Automatisierung. Die Logik-Engine ist erst der Anfang. In der Planung ist noch eine Datenaufzeichnung sowie eine Schnittstelle zur CometVisu. Meine anderen Projekte (Helios KWL Remote, Modbus2Knx und ekey-decoder) werde ich später auch als Plugin für den KAD auslegen. Dann spart man sich die mehrfachen Java Instanzen wenn man alles einsetzt.
                          Warum nicht das naheliegendste und "KNX Logic Engine"? KnxLE oder so...

                          Was müsste ich tun um das mal grob zum Laufen zu bekommen? Dazu habe ich nichts im Thread gefunden.. oder wieder überlesen? :/

                          Und um ganz deutlich zu machen, ich will hier gar nicht rumkritteln aber das Projekt spricht mich sehr an und versuche kritisches Feedback zu geben. Toll soweit!

                          Kommentar


                            #28
                            Zur Getter&Setter Geschichte:

                            Der fortgeschrittene ist sicherlich ein wenig weiter. Aber der Anfänger wird in jeder Einsteiger-Anleitung die er im Netz findet über getter&setter stolpern.

                            "die Logik auf eine GA zu 'setzen' "
                            listenTo() ... kümmert definiert die Gruppenadressen auf die man im Script lauschen will. Fällt die etwas sprechenderes ein?

                            setPA() ... setzt die physikalische Adresse der Logik. D.h wenn die Logik etwas sendet, dann mit dieser Absender-Adresse. Das ist optional und nicht verpflichtend. Finde das unheimlich praktisch wenn es darum geht heraus zu finden, welche der unter Umständen vielen Logiken die man hat gerade was über den Bus schickt (Busmonitor in der ETS). HS und Co. sendet immer mit derselben PA.
                            Ich kenne bisher keine Logikengine die das wirklich unterstützt. Wäre ein Alleinstellungsmerkmal ;-) Und "setze die PA dieser Logik auf XYZ" finde ich schon ziemlich sprechend. Was wäre denn dein Gegenvorschlag?

                            Warum nicht das naheliegendste und "KNX Logic Engine"? KnxLE oder so...
                            Du wirst lachen... Genau das war zwischendurch mal der Arbeitstitel für das Projekt. Aber je weiter ich daran gefeilt habe, desto eher bin ich bei einem universellen Daemon gelandet.
                            Die Logik-Engine ist nur ein Plugin des Daemons. Weitere Plugins werden sicherlich die Persistierung von Daten/Messwerten, die Anbindung von ekey, Dimplex-Wärmepumpen und Helios-Lüftungsanlagen, sowie ein Backend-Gateway für die CometVisu.

                            Was müsste ich tun um das mal grob zum Laufen zu bekommen? Dazu habe ich nichts im Thread gefunden.. oder wieder überlesen? :/
                            Am besten noch ein wenig warten. Ich hab viele (eigene) Teilprojekte, die nicht alle bei Github liegen und vor allen nicht alle auf MavenCentral zu finden sind. Muss die POMs noch anpassen und die einzelnen Teil-Artefakte noch in mein Maven Repo ziehen.
                            Dann kannst du entweder den Code auschecken und selbst bauen, oder du nimmst das "Distribution"-Release das man einfach entpacken und starten kann.

                            Vielleicht schaff ich beides diese Woche noch...

                            Zuletzt geändert von tuxedo; 14.09.2015, 08:48.

                            Kommentar


                              #29
                              Wo finde ich denn den .knxproj-Parser?
                              DistKV, Home Assistant, 1wire, KNX, Python, Asterisk, SMD-Lötkolben

                              Kommentar


                                #30
                                Noch nirgends. Geduld geduld....kommt alles noch.

                                Kommentar

                                Lädt...
                                X