>From 4aaa3aaad2ec2424f25cd942f006329607c5a4c7 Mon Sep 17 00:00:00 2001 From: Fulup Ar Foll Date: Fri, 1 Mar 2013 18:20:20 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=20Committer:=20Fulup=20Ar=20Foll=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gps2udp push gpsd data to multiple UDP host:port destination It can send AIS data to: ais-hub, shipfinder, marinetraffic,.... --- SConstruct | 11 ++++++++--- leapseconds.cache | 34 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/SConstruct b/SConstruct index e5d1f54..506eb60 100644 --- a/SConstruct +++ b/SConstruct @@ -947,6 +947,9 @@ env.Depends(gpsmon, [compiled_gpsdlib, compiled_gpslib]) gpspipe = env.Program('gpspipe', ['gpspipe.c'], parse_flags=gpslibs) env.Depends(gpspipe, compiled_gpslib) +gps2udp = env.Program('gps2udp', ['gps2udp.c'], parse_flags=gpslibs) +env.Depends(gps2udp, compiled_gpslib) + gpxlogger = env.Program('gpxlogger', ['gpxlogger.c'], parse_flags=gpslibs) env.Depends(gpxlogger, compiled_gpslib) @@ -956,7 +959,7 @@ env.Depends(lcdgps, compiled_gpslib) cgps = env.Program('cgps', ['cgps.c'], parse_flags=gpslibs + ncurseslibs) env.Depends(cgps, compiled_gpslib) -binaries = [gpsd, gpsdecode, gpsctl, gpsdctl, gpspipe, gpxlogger, lcdgps] +binaries = [gpsd, gpsdecode, gpsctl, gpsdctl, gpspipe, gps2udp, gpxlogger, lcdgps] if ncurseslibs: binaries += [cgps, gpsmon] @@ -1175,6 +1178,7 @@ base_manpages = { "gpsctl.1" : "gpsctl.xml", "gpsdctl.8" : "gpsdctl.xml", "gpspipe.1" : "gpspipe.xml", + "gps2udp.1" : "gps2udp.xml", "gpsdecode.1" : "gpsdecode.xml", "srec.5" : "srec.xml", } @@ -1220,7 +1224,7 @@ headerinstall = [ env.Install(installdir('includedir'), x) for x in ("libgpsmm.h binaryinstall = [] binaryinstall.append(env.Install(installdir('sbindir'), [gpsd, gpsdctl])) -binaryinstall.append(env.Install(installdir('bindir'), [gpsdecode, gpsctl, gpspipe, gpxlogger, lcdgps])) +binaryinstall.append(env.Install(installdir('bindir'), [gpsdecode, gpsctl, gpspipe, gps2udp, gpxlogger, lcdgps])) if ncurseslibs: binaryinstall.append(env.Install(installdir('bindir'), [cgps, gpsmon])) binaryinstall.append(LibraryInstall(env, installdir('libdir'), compiled_gpslib)) @@ -1326,6 +1330,7 @@ splint_table = [ ('splint-gpsdctl',['gpsdctl.c'],'gpsdctl', ['']), ('splint-gpsmon',gpsmon_sources,'gpsmon', ['-exportlocal']), ('splint-gpspipe',['gpspipe.c'],'gpspipe', ['']), + ('splint-gps2udp',['gps2udp.c'],'gps2udp', ['']), ('splint-gpsdecode',['gpsdecode.c'],'gpsdecode', ['']), ('splint-gpxlogger',['gpxlogger.c'],'gpxlogger', ['']), ('splint-test_packet',['test_packet.c'],'test_packet test harness', ['']), @@ -1569,7 +1574,7 @@ env.Alias('testregress', check) webpages = Split('''www/installation.html www/gpscat.html www/gpsctl.html www/gpsdecode.html www/gpsd.html www/gpsd_json.html www/gpsfake.html www/gpsmon.html - www/gpspipe.html www/gpsprof.html www/gps.html + www/gpspipe.html www/gps2udp.html www/gpsprof.html www/gps.html www/libgpsd.html www/libgpsmm.html www/libgps.html www/srec.html www/AIVDM.html www/NMEA.html diff --git a/leapseconds.cache b/leapseconds.cache index 4d8e7f2..f7f9f49 100644 --- a/leapseconds.cache +++ b/leapseconds.cache @@ -1,17 +1,17 @@ -315532800 -362793599 -394329599 -425865599 -489023999 -567993600 -631152000 -662688000 -709948799 -741484799 -773020799 -820454400 -867715199 -915148800 -1136073600 -1230768000 -1341100799 +315532800 # ('1979-12-31T23:59:60') +362793599 # ('1981-06-30T23:59:59') +394329599 # ('1982-06-30T23:59:59') +425865599 # ('1983-06-30T23:59:59') +489023999 # ('1985-06-30T23:59:59') +567993600 # ('1987-12-31T23:59:60') +631152000 # ('1989-12-31T23:59:60') +662688000 # ('1990-12-31T23:59:60') +709948799 # ('1992-06-30T23:59:59') +741484799 # ('1993-06-30T23:59:59') +773020799 # ('1994-06-30T23:59:59') +820454400 # ('1995-12-31T23:59:60') +867715199 # ('1997-06-30T23:59:59') +915148800 # ('1998-12-31T23:59:60') +1136073600 # ('2005-12-31T23:59:60') +1230768000 # ('2008-12-31T23:59:60') +1341100799 # ('2012-06-30T23:59:59') -- 1.7.10.4 >From 1d1f9cfa90f7eb7518ade532b41aca032018c346 Mon Sep 17 00:00:00 2001 From: "Fulup.ArFoll" Date: Fri, 1 Mar 2013 18:28:40 +0100 Subject: [PATCH 2/2] added gps2udp to support AIS push on aishub, marintraffic, shipfinder, ... --- gps2udp.c | 338 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gps2udp.xml | 114 ++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 gps2udp.c create mode 100644 gps2udp.xml diff --git a/gps2udp.c b/gps2udp.c new file mode 100644 index 0000000..033f0da --- /dev/null +++ b/gps2udp.c @@ -0,0 +1,338 @@ +/* + * gps2udp + * + * Dump NMEA to UDP socket for AIShub + * gps2udp -u data.aishub.net:1234 + * + * Author Fulup Ar Foll (directly inspired from gpspipe.c from gpsd official distrib) + * Date 01-march-2013 + * + * This file is Copyright (c) 2010 by the GPSD project + * BSD terms apply: see the file COPYING in the distribution root for details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef S_SPLINT_S +#include +#endif /* S_SPLINT_S */ + +#include "gpsd.h" +#include "gpsdclient.h" +#include "revision.h" + +#include +#include +#include +#include + + +static struct gps_data_t gpsdata; + +/* UDP socket variables */ +#define MAX_UDP_DEST 5 +static struct sockaddr_in remote[MAX_UDP_DEST]; +static int sock[MAX_UDP_DEST]; +static int udpchanel; + +/* gpsclient source */ +static struct fixsource_t gpsd_source; +static int flags; +static int debug=0; +static int aisonly=0; + +static int send_udp (char *nmeastring, int ind) { + char message [255]; + char *buffer; + int status, chanel; + + /* if string lenght is unknow make a copy and compute it */ + if (ind == 0) { + /* compute message size and add 0x0a 0x0d */ + for (ind=0; nmeastring [ind] != '\0'; ind ++) { + if (ind > (int)sizeof (message)) { + fprintf(stderr, "gps2udp: too big [%s] \n", nmeastring); + return -1; + } + message[ind] = nmeastring[ind]; + } + buffer = message; + } else { + /* use directly nmeastring but change last 2 byte */ + buffer = nmeastring; + ind=ind-2; + } + /* Add termination to NMEA feed for AISHUB */ + buffer[ind]='\n'; ind ++; + buffer[ind]='\r'; ind ++; + buffer[ind]='\0'; + + /* send message on udp chanel */ + for (chanel=0; chanel < udpchanel; chanel ++) { + status=sendto(sock[chanel],buffer,ind,0,&remote[chanel],sizeof(remote)); + if (status < ind) { + fprintf(stderr, "gps2udp: fail to send [%s] \n", nmeastring); + return -1; + } + } +return 0; +} + + +static int open_udp(char **hostport) +/* Open and bind udp socket to host */ +{ + struct hostent *hp; + char *hostname = NULL; + char *portname = NULL; + int portnum, chanel; + + for (chanel=0; chanel h_addr, (char *)&remote[chanel].sin_addr, hp->h_length); + remote[chanel].sin_port = htons(portnum); + } +return (0); +} + +static void usage(void) +{ + (void)fprintf(stderr, + "Usage: gps2udp [OPTIONS] [server[:port[:device]]]\n\n" + "-h Show this help.\n" + "-u Send UDP NMEA/JASON feed to host:port [multiple -u host:port accepted]" + "-n Feed NMEA.\n" + "-j Feed Jason.\n" + "-a Select !AISDM message only.\n" + "-c [count] exit after count packets.\n" + "-b Run in background as a daemon.\n" + "-d debug display packets.\n" + "-v Print version and exit.\n\n" + "You must specify one, or more, of -r, -R, or -w\n" + ); +} + +/* loop until we connect with GPSd */ +static void connect2gpsd (int restart) { + int delay,status; + + if (restart) gps_close (&gpsdata); + + /* loop until we reach GPSd */ + for (delay=10;;delay=delay*2) { + status = gps_open(gpsd_source.server, gpsd_source.port, &gpsdata); + if (status != 0) { + fprintf(stderr, "gps2udp: lost gpsd connection at %s:%s\n", + gpsd_source.server, gpsd_source.port); + sleep (delay); + } else { + if (debug > 0) fprintf(stdout, "gps2udp: connected to gpsd %s:%s\n", + gpsd_source.server, gpsd_source.port); + break; + } + } + /* select the right set of gps data */ + gps_stream(&gpsdata, flags, gpsd_source.device); + +} + +/* get date from gpsd */ +static int read_gpsd (char *message, int len) { + + struct timeval tv; + fd_set fds,master; + int result,ind; + char c; + int retry=0; + + // prepare select structure */ + FD_ZERO(&master); + FD_SET(gpsdata.gps_fd, &master); + + + /* loop until we get some data or an error */ + for (ind=0; ind 0) && (debug > 0)) fprintf (stdout," Retry=%d\n",retry); + + if (aisonly && message[0] != '!') { + if (debug >0) fprintf (stdout,"info [%d] %s\n", ind, message); + return (0); + } + + return (ind+1); + } else { + message[ind]= c; + } + break; + + case 0: /* no data fail in timeout */ + retry ++; + if (debug > 0) write (1,".",1); + + break; + + default:/* we lost connection with gpsd */ + connect2gpsd (true); + break; + } + } + message [ind]='\0'; + fprintf (stderr,"\n gps2udp: message to big [%s]\n", message); + return (-1); +} + + +int main(int argc, char **argv) { + bool daemonize = false; + long count = 0; + int option, status; + + char *udphostport[MAX_UDP_DEST]; + + flags = WATCH_ENABLE; + while ((option = getopt(argc, argv, "?habnjcdvl:u:")) != -1) { + + switch (option) { + case 'd': + debug=1; + break; + case 'n': + if (debug >0) fprintf (stdout, "NMEA selected\n"); + flags |= WATCH_NMEA; + break; + case 'j': + if (debug >0) fprintf (stdout, "JASON selected\n"); + flags |= WATCH_JSON; + break; + case 'a': + aisonly=1; + break; + case 'c': + count = strtol(optarg, 0, 0); + break; + case 'b': + daemonize = true; + break; + case 'u': + if (udpchanel > MAX_UDP_DEST) { + fprintf (stderr, "gps2udp: to many UDP destination (max=%d)\n",MAX_UDP_DEST); + } else { + udphostport [udpchanel]= optarg; + udpchanel ++; + } + break; + case 'v': + (void)fprintf(stderr, "%s: %s (revision %s)\n", + argv[0], VERSION, REVISION); + exit(0); + case '?': + case 'h': + default: + usage(); + exit(1); + } + } + + /* Grok the server, port, and device. */ + if (optind < argc) gpsd_source_spec(argv[optind], &gpsd_source); + else gpsd_source_spec(NULL, &gpsd_source); + if (gpsd_source.device != NULL) flags |= WATCH_DEVICE; + + /* check before going background if we can connect to gpsd */ + connect2gpsd (false); + + /* Open UDP port */ + if (udpchanel > 0) { + status = open_udp(udphostport); + if (status !=0) exit (1); + } + + /* Daemonize if the user requested it. */ + if (daemonize) { + if (daemon(0, 0) != 0) { + fprintf(stderr, "gps2udp: demonization failed: %s\n", strerror(errno)); + } + } + + /* Infinit loop to get date from GPSd and push them to AIShub */ + for (;;) { + char buffer [1024]; + int len; + + len = read_gpsd (buffer, sizeof (buffer)); + + /* ignore empty message */ + if (len > 3) { + if (debug > 0) fprintf (stdout,"---> [%d] -- %s\n", len,buffer); + if (udpchanel > 0) send_udp (buffer, len); + } + + if (count > 0) { + if (count-- < 0) { + /* completed count */ + fprintf (stderr, "gpsd2udp normal exit after [%d] packets\n",(int)count); + break; + } + } + } + +exit (0); +} diff --git a/gps2udp.xml b/gps2udp.xml new file mode 100644 index 0000000..46ea69c --- /dev/null +++ b/gps2udp.xml @@ -0,0 +1,114 @@ + + + + +01 Marc 2013 + +gps2udp +1 +The GPSD Project +GPSD Documentation + + +gps2udp +tool to connect to gpsd and push sentences to aishub, marinetraffic, .... + + + + + gps2udp + -h + -n + -j + -a + -u hostname:udpport + -c count + -d + -v + + server + :port + :device + + + + + +DESCRIPTION + +gps2udp is a tool to connect +to gpsd and output the received +sentences to one or many UDP host:port destinations. This makes the program useful to feed AIS information from gpsd to aishub, marinetraffic, shipfinder,... + +gps2udp does not require root +privileges, and can be run concurrently with other tools connecting +to the local gpsd without causing problems. + +The output will consist of one or both of NMEA (-n option) or Jason (-j option) +gpsd sentences. The output are sent to one or many destinations host through a UDP network socket (-u host:port options) . + +Optionally a server, TCP/IP port number and remote device can be given. +If omitted, gps2udp connects to localhost on +the default port (2947) and watches all devices opened by +gpsd. + +gps2udp may be run as a daemon (-b option). + +gps2udp is design to run smoothly in background, it reconnecte automatically to gpsd is ever this one is restarted. For debug perporse, there is an option to exit gracefully after a given count of packets (-c option). + + +OPTIONS + +-h makes gps2udp print +a usage message and exit. + +-n causes NMEA sentences to be output. +-j causes JASON sentences to be output. +-u host:port UDP destination for output sentenses (up to five destinations). + +-a output only AIS messages. +-b causes gps2udp to run as a daemon. +-n [count] causes [count] sentences to be output. +gps2udp will then exit gracefully. + +-d prints sent packet on stdout. +-v prints the version, then exits. + + + +EXAMPLE +With a running gpsd accessible on the network + +gps2udp -d -n -u data.aishub.net:2222 + will collect data from localhost:gpsd display them on stdout and send a copy to test aishub in NMEA format. + +gps2udp -a -n -b -u data.aishub.net 2222 -u 5.9.207.224 5321 -u 109.200.19.151 4001 vz-fulup.vpn:2947 will collect data from a remote gpsd located on vz-fulup.vpn host, will filter AIS messages and send them to 3 destination [aishub, marinetraffic, shipfinder] in NMEA format, command is running in background mode + + +SEE ALSO + +gpsd8, +gps1, +libgps3, +libgpsd3, +gpsprof1, +gpsfake1, +gpsctl1, +gpscat1. +gpsmon1. + + + +AUTHOR + +Fulup Ar Foll fulup (à) sinagot.net. + + + + + -- 1.7.10.4