Ankündigung

Einklappen
Keine Ankündigung bisher.

Socket weiterleiten

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [wiregate] Socket weiterleiten

    Ich möchte gern ein UDP-Datagramm auf weitere Ports verteilen. Das hat schonmal funktioniert aber ich komme auf keinen grünen Zweig mehr.

    Hintergrund:

    Es wird eine Socketverbindung #1 vom Seriellen Port auf UDP gemacht. Auf diese soll sich dann ein Perl-Daemon verbinden und die Daten auslesen und schonmal leicht aufarbeiten (Telegramme sammeln).

    Diese Socketverbindung will ich nun mit #2 weiterleiten. Darauf soll sich dann das Plugin verbinden. Damit schaffe ich es die ankommenden Daten vorab etwas zu sortieren und die "Belastung" zu minimieren (timeouts).
    Weiterhin kann ich die Socketverbindung #2 ja dann nutzen um direkt aus dem Plugin auf den seriellen Port zu schreiben oder im Zweifel auch mal "heiß" vom seriellen Port zu lesen.

    Das ganze hat, zumindest die Weiterleitung von Socket #1 zu Socket #2 geklappt. Jetzt gehts aber irgendwie nicht mehr. Hab ich da irgendwo nen Konfigurationsfehler, war es Zufall dass es ging? Varianten hab ich eigentlich schon alle durch. Mein Daemon verbindet sich auch ganz brav mit Socket #1.


    Danke und Gruß
    Mirko
    Angehängte Dateien
    Umgezogen? Ja! ... Fertig? Nein!
    Baustelle 2.0 !

    #2
    Ich hab jetzt das spezielle Grundgerüst fertig, der Daemon läuft und sendet die Telegramme als Datenpaket an das Plugin.
    Nun brauche ich im Plugin 2 Socketverbindungen.

    Socket #1 soll subscribed werden und mit if ($fh) ausgelesen werden (klappt als Standalone-Plugin perfekt). Die Daten kommen aus dem Daemon.
    Socket #2 soll auf Anfrage (durch GA) senden und "heiß" lesen.

    Das Plugin startet, verbindet sich zu beiden Sockets und liest einen Satz des filehandle ein, danach ist Schluss und es bleibt hängen. Mache ich ein Plugin mit einer Socketverbindung dann wird anstandlos jedes filehandle bearbeitet, also muss es eigentlich an den zwei Socketverbindungen liegen. Anbei mal der wichtigste Code. Ich dachte ich vergebe einfach die Nummern im Code und mach das subscribe socket dann nur auf den Socket auf den das Plugin horchen soll.

    Code:
    #return;
    $plugin_info{$plugname.'_cycle'} = 66;
    use warnings;
    use strict;
    
    my $debug = 1; # 0=zero log messages / 1=all log messages / 2=only value messages
    
    
    #### CREATE SOCKETS ####
    my $socknum = "1000";	# Do not change !!!
    my $daemon_recv_ip = "localhost"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
    my $daemon_recv_port = "50201"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
    
    if (!$socket[1000]) { # socket erstellen
            $socket[1000] = IO::Socket::INET->new(LocalPort => $daemon_recv_port,
                                      Proto => "udp",
                                      LocalAddr => $daemon_recv_ip,
                                       )
        or return ("open of $daemon_recv_ip : $daemon_recv_port failed: $!");
    
        $socksel->add($socket[1000]); # add socket to select
    
        $plugin_socket_subscribe{$socket[1000]} = $plugname; # subscribe plugin
        plugin_log($plugname,'Socket verbunden. Daemon-Plugin Socket Nummer: ' . 1000);
        return "opened Socket 1000";   
    }
    
    #### CREATE SOCKETS ####
    my $socknum = "1001"; # Do not change
    my $ebus_send_ip = "localhost"; # Sendeport (UDP, siehe in Socket-Einstellungen)
    my $ebus_send_port = "50111"; # Sendeport (UDP, siehe in Socket-Einstellungen)
    my $ebus_recv_ip = "localhost"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
    my $ebus_recv_port = "50110"; # Empfangsport (UDP, siehe in Socket-Einstellungen)
    
    if (!$socket[1001]) { # socket erstellen
            $socket[1001] = IO::Socket::INET->new(LocalPort => $ebus_recv_port,
                                      Proto => "udp",
                                      LocalAddr => $ebus_recv_ip,
                                      PeerPort  => $ebus_send_port,
                                      PeerAddr  => $ebus_send_ip,
                                      ReuseAddr => 1
                                       )
        or return ("open of $ebus_recv_ip : $ebus_recv_port failed: $!");
    
        $socksel->add($socket[1001]); # add socket to select
    
        plugin_log($plugname,'Soket verbunden. eBus-Serial Socket Nummer: ' . 1001);
        return "opened Socket 1001";   
    }
    
    #### MAIN ####
    
    my ($string,$data,@data,$QQ,$ZZ,$PB,$SB,$DB,$DB1);
    
    
    #### RECIVE DATA ####
    if ($fh) { # Wenn eBus ein Telegramm sendet, wird ab hier der entsprechende Status ausgelesen.
    while ($string = <$fh>) {
    	chomp $string;
    	
    	if ($debug = 1){plugin_log($plugname,"$string")}
    	
    	my $string_format =~ s/(.{2})/$1/g;
    	if ($debug = 1){plugin_log($plugname,"Telegramm: $string")}
    	
    	&check($string);
    }}
    
    
    ###################
    ### S E N D E N ###
    ###################
    
    sub send {
    if ($debug = 1) {plugin_log($plugname, "Sub Senden erreicht !");}
    my $cmd = shift;
    my $sync = 0;
            while ($sync < 1)
                    {
                            my $buf;
                            recv($socket[1001],$buf,1,0); # unbuffered read from socket
                            #read($socket[$socknum],$buf,1);
                            my $bufhex = $buf;
                            $bufhex =~ s/(.)/sprintf("%.2X",ord($1))/eg;
                            if ($debug = 1) { plugin_log($plugname, "Buffer: $bufhex");}
                            
                                    if ($bufhex eq "AA")    # AA = SYNC ... hier warten wir jetzt auf das SYNC Zeichen und senden dann
                                    {
                                    $sync = 1;
                                    if ($debug = 1) { plugin_log($plugname, "Sync Zeichen gelesen");}
                                    my $raw = $cmd;
                                    $raw =~ s/([0-9a-f]{2})/chr( hex( $1 ) )/gie;      # !!! Umwandlung des Hex-Strings
                                    if ($debug = 1) { plugin_log($plugname, "send: $cmd");}
                                    syswrite($socket[1001], $raw);
                                    last;   # Nun aber raus aus der Schleife
                                    }
                                    else
                                    {redo;}
                    }
                 
    }
    Umgezogen? Ja! ... Fertig? Nein!
    Baustelle 2.0 !

    Kommentar


      #3
      Ich kann mit dem Fragment noch nicht ganz folgen
      Also, nur so als Tipp vom Küken:
      a) auf dem seriellen Port rumzuwurschteln geht zwar technisch aber es hat viele gute Gründe warum ich das vermeide und den socat zwischenschalte..
      b) sowas erstmal standalone probieren, wenns rennt hat die Plugin-Laufzeitumgebung ihre Vorteile aber zum entwickeln nur bedingt hilfreich.

      Ansonsten braucht die Glaskugel mehr Details, was geht und was nicht..

      Makki
      EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
      -> Bitte KEINE PNs!

      Kommentar


        #4
        Also ich versuche es nochmal langsam.
        Das ganze Konstrukt besteht aus zwei Sockets, einem Plugin und einem Daemon.

        Socket #1:
        Wird momentan manuell aufgerufen: socat - udp:localhost:50201
        Dieser Socket dient dem senden von Daten aus dem Daemon zum Plugin.

        Socket #2:
        Übers webmin eingerichtet: socat /dev/ttyUSB0,raw,b2400,echo=0 udp-datagram:localhost:50110,bind=localhost:50111,reus eaddr
        Dieser Socket verbindet sowohl Damon als auch Plugin mit der seriellen Schnittstelle.

        Daemon:
        Der Daemon hat zwei eingerichtete Socketverbindungen. Er liest die Daten aus dem Socket#2, verarbeitet diese zu lesbaren Telegrammen und sendet dann z.B. 20 gesammelte Telegramme über Socket#1 an das Plugin.

        Plugin:
        Das Plugin soll einerseits Daten empfangen und auch senden. Das Empfangen geschieht je nach Befehl auf unterschiedlichen Sockets. I.d.R. soll via if($fh) auf Socket#1 gehorcht werden. Dann kommen 20 Telegramme und die werden ausgewertet. Die Laufzeit des Plugins ist dabei marginal klein. Diese Funktion als einzelnes Plugin klappt auch zuverlässig. Die Daten werden verarbeitet und auf den Bus oder in rrds geschrieben.
        Weiterhin besteht über das Plugin die Möglichkeit auch Daten zu senden. Beim senden muss auf ein SYNC-Zeichen auf der seriellen Schnittstelle gewartet werden. Da kommt jetzt also Socket#2 ins Spiel. Von diesem wird "heiß" gelesen und dann das entsprechende Telegramm abgesetzt. Auch dieser Teil funktioniert als Standalone-Plugin.

        Da ich noch nicht weiß wohin mich die Entwicklung so treibt möchte ich natürlich beide Möglichkeiten im Plugin haben. Also einmal "heiß" lesen (eher die Ausnahme) oder eben einfach nur auf die Telegramme die mir der Daemon schickt zu reagieren. Dies bedingt also zwei Sockets im Plugin.

        Der Fall ist jetzt so dass beide Socketverbindungen wohl aufgebaut werden aber nur einmalig das if($fh) abgearbeitet wird. Grunsätzlich schient es also zu funktionieren. Der Daemon kann ja auch mit 2 Socketverbindungen umgehen.

        Evtl. könnten 2 Fragen das ganze klären:

        1. Wie richte ich im Webmin socat - udp:localhost:50201 ein ? Meine Varianten führten zu keinem laufenden Socket.

        2. Was braucht es um ein Socket zu subscriben und damit ein if ($fh) das Plugin startet.
        Beim zu subscribenden Socket (#1) habe ich sowohl $socksel->add($socket[$socknum]); als auch $plugin_socket_subscribe{$socket[$socknum]} = $plugname; mit der entsprechenden socknum eingetragen. Beim Socket für das "heiße" lesen hab ich das rausgenommen weil ich da nicht automatisch "Rohdaten" gesendet bekommen will sondern nur auf Anfrage lese.

        Ich hoffe das ist etwas verständlicher.
        Gruß Mirko
        Umgezogen? Ja! ... Fertig? Nein!
        Baustelle 2.0 !

        Kommentar


          #5
          Ist es denn generell möglich sich in einem Plugin auf 2 Sockets zu verbinden und nur eines als $fh zu subscriben?
          Umgezogen? Ja! ... Fertig? Nein!
          Baustelle 2.0 !

          Kommentar


            #6
            Zitat von JuMi2006 Beitrag anzeigen
            Also ich versuche es nochmal langsam.
            Ich lese auch ganz langsam

            1. Wie richte ich im Webmin socat - udp:localhost:50201 ein ? Meine Varianten führten zu keinem laufenden Socket.
            Kaum sinnvoll, weil "-" bedeutet stdout, da muss ja irgendwas drun herum laufen was liest/schreibt.
            Eine Variante wäre eine fifo-pipe z.B. in /tmp (mkfifo) aber nun verlassen wir deutlich den Sektor wo "socat for dummys" noch Sinn macht
            Also da bleibt nur noch der Vorteil, das der socat halt automatisch im Monit steht, "einfach" ist anders..

            2. Was braucht es um ein Socket zu subscriben und damit ein if ($fh) das Plugin startet.
            Das ist gewachsen, im Kern beides (was man sich aus heutiger Sicht sparen könnte, bleiben wird nur der $plugin_socket_subscribe)

            Zitat von JuMi2006 Beitrag anzeigen
            Ist es denn generell möglich sich in einem Plugin auf 2 Sockets zu verbinden und nur eines als $fh zu subscriben?
            Ja, socket anlegen und nicht subscriben dann wirds ignoriert, der Socket ist ja auch nur eine pipe die per select() abgefragt wird, wenn nicht, ists dem wiregated auch egal..

            Makki
            EIB/KNX & WireGate & HS3, Russound,mpd,vdr,DM8000, DALI, DMX
            -> Bitte KEINE PNs!

            Kommentar

            Lädt...
            X