UDP-Meldungen empfangen und seriell ausgeben
Vor einer ganzen Weile habe ich ein Programm für den Raspberry geschrieben welches NMEA-Daten von einem GPS-Empfänger per UDP im Netzwerk verteilt: Broadcast von GPS-Daten.
Jezt kam der Wunsch auf, diese Daten wieder zu empfangen und auf ein serielles Port auszugeben. Um das Programm etwas allgemeiner zu machen, lasse ich es auf ein beliebiges File schreiben:
./ReceiveGPS /dev/ttyUSB0
Damit das auf der seriellen Schnittstelle richtig funktioniert, muss diese vorgängig mit stty -F /dev/ttyUSB0 ... konfiguriert werden.
Das Programm ist für den Raspberry gedacht, aber es sollte auch auf jedem anderen Linux-System laufen
Die Source des Programms
/******************************************************************************/ /* */ /* FILE: ReceiveGPS.cpp */ /* */ /* Reads GPS data from a UDP socket and sends it to a serial port */ /* ============================================================== */ /* */ /* V1.00 13-MAR-2017 Te */ /* */ /******************************************************************************/ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /****************************/ int CreateSocket( int port ) /****************************/ { // Create a socket int sock = socket( AF_INET, SOCK_DGRAM, 0 ) ; if( sock == -1 ) { fprintf( stderr, "CreateSocket: socket failed\n" ) ; return -1 ; } // Bind it to the local address struct sockaddr_in address ; memset( &address, 0, sizeof(address) ) ; address.sin_family = AF_INET ; address.sin_addr.s_addr = htonl( INADDR_ANY ) ; address.sin_port = htons( port ) ; if( bind(sock,(struct sockaddr *)&address,sizeof(address)) == -1 ) { fprintf( stderr, "CreateSocket: bind failed\n" ) ; close( sock ) ; return -1 ; } return sock ; } /**********************************/ int main( int argc, char *argv[] ) /**********************************/ { fprintf( stderr, "ReceiveGPS V1.00\n" ) ; if( argc != 2 ) { fprintf( stderr, "usage: %s devicename\n", argv[0] ) ; return 1 ; } int fd = open( argv[1], O_WRONLY ) ; if( fd == -1 ) { fprintf( stderr, "error: can't open %s\n", argv[1] ) ; return 2 ; } int socket = CreateSocket( 10110 ) ; if( socket == -1 ) { fprintf( stderr, "error: can't create socket\n" ) ; close( fd ) ; return 3 ; } struct sockaddr_in address ; char line[256] ; int count ; int size ; int c ; for( ;; ) { socklen_t length = sizeof( address ) ; size = recvfrom( socket, line, sizeof(line), 0, (struct sockaddr *)&address, &length ) ; if( size < 1 ) { fprintf( stderr, "error: recvfrom failed\n" ) ; break ; } for( count = 0; count < size; count += c ) { c = write( fd, line + count, size - count ) ; if( c < 1 ) { fprintf( stderr, "error: write failed\n" ) ; } } } close( fd ) ; close( socket ) ; return 0 ; }
Compilieren und starten
Compilieren geht mit einer einzigen Zeile:
g++ -Wall -o ReceiveGPS ReceiveGPS.cpp
Das Port ist hartcodiert, so dass es sicher zum Sendeprogramm passt. Darum verlangt es einzig einen Filenamen als Argument. Dieses File wird in den meisten Fällen der Pfad zum seriellen Device sein:
./ReceiveGPS /dev/ttyUSB0
Download der Source
Damit Sie den Code nicht von der Webseite kratzen müssen, gibt es ihn hier zum Download: Source von ReceiveGPS.cpp