Hallo,
ich bau gerade die in FHEM integrierte UPnP Library in mein DLNA Modul (https://forum.fhem.de/index.php?topic=39706.0) ein. Da ich keine separate Mainloop aus der ControlPoint.pm verwenden will, welche dann wieder in einem eigenen Prozess laufen müsste, würde ich gerne die Sockets aus ControlPoint.pm an die FHEM Mainloop übergeben.
Problemstellung
Jedes DLNA Device kann mehrere offene Sockets haben (Subscriptions um auf Events zu warten, auf Suchergebnisse warten, SSDP Events von neuen DLNA Devices abfragen). DevIO unterstützt aber nur 1 Device per Modul. Gibt es eine Möglichkeit mehrere Sockets an die FHEM Mainloop zu übergeben?
Aktuelle Lösung
Im Moment verwende ich InternalTimer und rufe jedes Sekunde die "handleOnce" Funktion mit allen Sockets auf. Diese Lösung gefällt mir nicht wirklich, da ich damit quasi eine neue "Mainloop" innerhalb des Moduls baue.
Meine Idee
Jedes Modul kann Sockets in der FHEM Mainloop registrieren. Z.B. mit "registerSocket($hash, $SOCKET, \&callbackRead);" sobald Daten am Socket anstehen, ruft die Mainloop "X_Read($hash, $SOCKET);" auf wo man innerhalb des Moduls die Daten dann lesen und verarbeiten kann. Was haltet ihr davon?
Falls es schon eine bestehende Lösung gibt bitte ich um Infos dazu. Danke.
Gruß
Dominik
Hallo Dominik,
vielleicht übersehe ich da was bei deinem Ansatz, aber wirf bitte noch einmal einen Blick auf TcpServerUtils Open/Accept und fhem.pl. Solange der Key für die SelectList eindeutig ist, ruft FHEM die ReadFn auf. Dabei spielt keine Rolle, ob mehrere Einträge vom gleichen Modul in der SelectList vorhanden sind. Reicht das nicht?
Grüße,
Jens
Hi Jens,
die TcpServerUtils kannte ich noch gar nicht :o
Der Key dürfte in der SelectList eindeutig werden, aber danach arbeitet sowohl TcpServerUtils als auch DevIO immer mit $hash->{FD}. Da ich aber von ControlPoint.pm eine Liste an Sockets zurück bekomme, bräuchte ich ein $hash->{FDs} - also eine Liste an Sockets die geprüft werden. Weil ansonsten wird bei jedem Aufruf immer nur ein $hash->{FD} geprüft und nicht alle 3-6 die ich teilweise habe.
Gruß,
Dominik
Hi Diminik,
ich kenne ControlPoint nicht, aber kannst du da nicht den FD herausholen und pro Socket ein Hidden Device definieren?
Grüße,
Jens
schau dir mal das plex oder fakeRoku modul an. dort werden diverse ssdp broadcast und multicast sockets zum lesen und schreiben sowie tcp/ip http sockets ebenfalls für beides verwendet. alles in einem modul mit der FHEM main loop ohne blockieren oder pollen.
gruss
andre
Hi Andre,
du legst also jeweils einen neuen Hash an und gibst den in die selectlist. Hab ich das richtig gesehen?
In der plex_Read Funktion prüfst du dann welcher Hash verarbeitet wird und liest die Daten aus.
Gruß,
Dominik
ja. so ungefähr. wobei jeder hash im prinzip einem eigenen mehr oder weniger unabhängigen FHEM device entspricht. plex_Read ist dann für alle instanzen zuständig. jede instanz kann benötigte daten im eigenen hash ablegen.
gruss
andre
Ich wollte gerade deine Lösung mit "CHash" in mein Modul integrieren, aber irgendwie frage ich mich, ob das auch eine saubere Lösung ist?? Bei mir ändert sich nämlich auch dynamisch die Anzahl der Sockets die geprüft werden müssen. Daher müsste ich doch wieder jede Sekunde mit InternalTimer neue CHashes anlegen oder löschen.
Eine einfache halbwegs schöne Lösung wäre doch, dass jedes Modul eine MainLoopFn registrieren kann, oder? Und dann ruft die FHEM Mainloop aus allen Modulen genau diese MainLoopFn auf.
warum ändert sich die anzahl der sockets bei dir sekündlich?
die sollte sich doch nur ändern wenn devices im netz erscheinen oder wieder verschwinden. und vielleicht noch wenn es benutzerinteraktionen gibt.
und selbst wenn sich die anzahl der sockets ändert brauchst du doch keinen timer. sockets die du selber auf machst fügst du beim öffnen hinzu, sockets die von aussen aufgemacht werden fügst du nach dem accept hinzu, für udp musst du gar nichts hinzufügen.
gruss
andre
Da hast du recht, die Anzahl der Devices ändert sich nur, wenn ich über den Such-Socket etwas rein bekomme. Dann muss ich also doch nicht alle Sekunden prüfen.
Aber mal ehrlich, ist es nicht trotzdem quatsch einen ganzen Hash mit Rauminfo, etc. anzulegen nur weil man einen Socket der Mainloop hinzufügt? Das sollte doch besser gehen.
ein hash ist nicht schwergewichtig.
außerdem wirst du in 99% aller fälle merken das du dir zusätzlich zum socket doch noch irgendwelche dinge merken willst. und da bietet sich der hash auch wieder an. er entkoppelt und kapselt wunderbar. stell ihn dir einfach als instanz einer klasse vor.
außerdem ist es in für die fhem main loop die offizielle schnittstelle.
du müsstest ja sonst auch irgendwo ablegen welches modul bzw. readFn aufgerufen werden soll wenn daten da sind. auch das steckt im hash.
wenn du temporary und hiddenroom setzt ist der hash auch nicht weiter sichtbar und stört nicht.