Article: 91680 of sci.geo.satellite-nav
From: Joao Pedro Goncalves <joaop@iscsp.utl.pt>
Newsgroups: sci.geo.satellite-nav
Subject: ANNOUNCE: Perl module for GPS Garmin receivers.
Date: Thu, 11 Feb 1999 17:31:44 +0000
Organization: Navegante Lda.
Lines: 67
Message-ID: <36C31400.20D2A64@iscsp.utl.pt>
NNTP-Posting-Host: orodruin.esoterica.pt
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: anubis.esoterica.pt 918754332 27696 195.22.0.166 (11 Feb 1999 17:32:12 GMT)
X-Complaints-To: news@esoterica.pt
NNTP-Posting-Date: 11 Feb 1999 17:32:12 GMT
X-Mailer: Mozilla 4.5 [en] (X11; I; Linux 2.0.35 i686)
X-Accept-Language: en
Cache-Post-Path: orodruin.esoterica.pt!joaop@lis422.esoterica.pt
X-Cache: nntpcache 2.3.3 (see http://www.nntpcache.org/)
Path: news1.meer.net!news3.best.com!news2.best.com!news.maxwell.syr.edu!news.new-york.net!uunet!ffx.uu.net!in3.uu.net!news.planetc.com!news.esoterica.pt!not-for-mail
Xref: news1.meer.net sci.geo.satellite-nav:91680


Hi, i've been writing a perl module for easy interfacing in scripts with

a GRMN/GRMN compatible GPS.

This way it will be easier to integrate a GPS receiver in a web server
cgi(where the hell my laptop is?), or track logging etc..

If you use this please mail me with some feedback, it's still quite
alpha but what i use is already implemented.

This was only tested on Linux with a Garmin GPS II+. As for the receiver

i've followed the Official Garmin spec, so it must be ok to every
receiver that implements this well.

You can download it from:

http://www.iscsp.utl.pt/joaop/work_in_progress/GPS-Garmin-0.02.tar.gz


Installation and use is quite easy:

$ gzip -d GPS-Garmin-0.02.tar.gz
$ tar zvxf GPS-Garmin-0.02
$ cd GPS-Garmin-0.02
$  perl Makefile.PL
$  make
$  make install

Sample script:


#!/usr/bin/perl -w


use GPS::Garmin;

$gps = new GPS(  'Port'      => '/dev/ttyS0',
                             'Baud'      => 9600,
                           ) or die "Cannot establish connection with
the receiver: $!";

($lat,$lon) = $gps->get_position;

print "My Latitude: $lat \n
         My Longitude: $lon \n
        ";


$num = $gps->number_of_tracks;

print "I have $num tracks in my log.\n";

for($i=0;$i < $num;$i++) {
     ($lat,$lon,$time) = $gps->grab_trk;
     print "Lat: $lat Lon: $lon Time:" . localtime($time) . "\n";
}


Thanks.

Joao Pedro Gonçalves
Navegante Lda.





Article: 116985 of sci.geo.satellite-nav
Message-ID: <39CFE6F3.ED7A2189@gte.net>
From: Mike Ramsey <res049ru@gte.net>
Reply-To: mramsey@caicosdream.com
Organization: Caicos Dream
X-Mailer: Mozilla 4.75 [en] (X11; U; Linux 2.2.5-15 i686)
X-Accept-Language: en
MIME-Version: 1.0
Newsgroups: sci.geo.satellite-nav
Subject: Re: PERL and GPS
References: <%I1y5.5514$gi1.110549@news.magma.ca>
Content-Type: multipart/mixed;
 boundary="------------ACAA1DB6C13B63F83B235A4F"
Lines: 383
X-Trace: /b4RlaISx06zucu82W52ZWmWEkvt1uD9/XT9n2zDFFLIAsvl1khb1eH06/crmkyU/NHfmHkjYiA9!f1HvDev5ofU5pWGHXIJffmuAZyS4W/axlkw7+e+j1UDdAruunHDADxqFc1TFWA==
X-Complaints-To: abuse@gte.net
X-Abuse-Info: Please be sure to forward a copy of ALL headers
X-Abuse-Info: Otherwise we will be unable to process your complaint properly
NNTP-Posting-Date: Tue, 26 Sep 2000 00:12:57 GMT
Distribution: world
Date: Tue, 26 Sep 2000 00:12:57 GMT
Path: news.meer.net!nntp1.ba.best.com!news1.best.com!newshub.sdsu.edu!news-hog.berkeley.edu!newsfeed.berkeley.edu!ucberkeley!paloalto-snh1.gtei.net!news.gtei.net!dfiatx1-snr1.gtei.net.POSTED!not-for-mail
Xref: news.meer.net sci.geo.satellite-nav:116985

This is a multi-part message in MIME format.
--------------ACAA1DB6C13B63F83B235A4F
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Here's a couple of scripts I wrote; one to send, one to receive. 
They're not very refined but they get the data in & out.  I use another
script to post the waypoints to a Postgres database.  I also have one
that writes a DXF file so I can plot them.  This is handy because I can
update the database with more meaningful waypoint names and messages. 
Then download the edited waypoints back to the GPS.

You're on your own since there's no documentation, comments, etc.  But
anyone attempting this with Perl probably knows enough to figure it
out.  The hard part was handling the input from the GPS.  You need to
keep reading the port until you get the crlf at the end of the line.

BTW, I have a 315 and connect it to a laptop running Linux.  YMMV with
different hardware/OS.

My frustration now is that my goal was to tie the waypoints to pictures
taken with my digital camera (Sony MVC83).  I can get a track from the
315 but it doesn't include the time stamp I want to correlate to the
photos.  It was suggested that I just click the Mark button to make a
waypoint for each shot.  Problem is that Magellan's waypoint format
doesn't even allow for a timestamp.  I.e. the track format allows time
but the track data doesn't save it; the waypoint data has the time but
the format doesn't allow it.  Bummer.

Good Luck,
Mike Ramsey
--------------ACAA1DB6C13B63F83B235A4F
Content-Type: application/x-perl;
 name="gps.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="gps.pl"

#!/usr/bin/perl

use FileHandle;
use Device::SerialPort;

$hand=0;

opengps();

sendgps("CMD,VERSION");

$done=$port->write_drain;
while (! $port->write_drain) {print "$done flushing\n";}

$in=gpsin();
($rcmd,$fields,$cs1,$cs2)=decodegps($in);
($pid,$sid,$name) = split ",",$fields;

print STDERR "Connected to $name\nSoftware Ver $sid\n";

#sendgps("CMD,HANDON");$hand=1;
#sendgps("CMD,TON");

print STDERR "Downloading Waypoints\n";
sendgps("CMD,WAYPOINT");
#sendgps("CMD,ROUTE");
#sendgps("CMD,TRACK,");

while ($in=gpsin())
	{
        print STDERR $in;
	chomp $in;

	($cmd,$fields,$cs1,$cs2)=decodegps($in);

	#printf "command %s fields %s cs %02x %02x\n",$cmd,$fields,$cs1,$cs2;

	if ($cmd =~ m/CMD/ && $fields =~ /END/)
                {
                $port->close;
                print STDERR "Done.\n";
                exit;
                }

	@wp = split ",",$fields;

	$lat = shift @wp; $lata = shift @wp;
	$lon = shift @wp; $lona = shift @wp;
	$alt=shift @wp; $alta=shift @wp;
	$name = shift @wp;
	$mesg = shift @wp;
	$icon = shift @wp;

	#printf "waypt %s at %f%s %f%s %f%s mesg %s\n",
	#	$name,$lat,$lata,$lon,$lona,$alt,$alta,$mesg;
	printf "%s,%f,%s,%f,%s,%f,%s,%s,%s\n",
		$name,$lat,$lata,$lon,$lona,$alt,$alta,$mesg,$icon;
	}

$port->close;

sub opengps
        {

        $dev="/dev/ttyS0";
        $quiet=0;
        $lock="/tmp/gps.lock";
        #my $stty=`/bin/stty -g <$dev`;
        
        $port=new Device::SerialPort ($dev,$quiet,$lock)
                || die "Can't open port $dev:$!\n";

        $port->baudrate(4800);
        $port->parity("none");
        $port->databits(8);
        $port->stopbits(1);
        $port->handshake("none");
        $port->are_match("\r\n");
        $port->write_settings;

        print STDERR "Serial port to GPS opened \n";
        } 
sub checksum
	{
	my ($string) = @_;
	my $sum = 0;

	#printf ">>%s<<\n",$string;
	@slist = split (//,$string);
        shift @slist;pop @slist;

	foreach $char (@slist)
		{
		$byte = unpack("C",$char);
		$sum ^= $byte;

		#printf  "c%s b%x s%x\n",$char,$byte,$sum;
		}
	return $sum;
	}	

sub sendgps
	{
	my ($cmd) = @_;
	my $mycmd = sprintf "\$PMGN%s*",$cmd;

	$cs = checksum($mycmd);

	$data=sprintf "%s%02x\r\n",$mycmd,$cs;
	$ctout=$port->write($data);
        #print "sent $ctout chars in >$data<\n";

	if ($hand && ( $cmd !~ /CSM/))
		{
		$/="\n";
		$_=$port->input;
		#print STDERR "resp $_\n";
		($rcmd,$fields,$cs1,$cs2)=decodegps($_);
		$rcs=hex($fields);
		if (($rcmd !~ /CSM/) || ($rcs != $cs))
			{
                        $port->close;
			die "CS error sending $cmd $fields,$cs\n";
			}
		}

	return $cs;
	}

sub decodegps
	{
	my ($str) = @_;

	#print "recv $str\n";

	$str =~ m/\$PMGN([A-Z][A-Z][A-Z]),(.*)\*([0-9a-fA-F][0-9a-fA-F])/;

	$cmd = $1;
	$fields = $2;
	$cssent = hex($3);

	$cmdstr=sprintf "\$PMGN%s,%s\*",$cmd,$fields;
	$cscalc = checksum($cmdstr);

	if ($cssent != $cscalc)
                {
                $port->close;
	        die "CS error receiving $cmd $cssent $cscalc\n";
                }
	$hs=sprintf "CSM,%02x",$cscalc;
	sendgps($hs) if $hand && $cmd !~ /CSM/;

	return ($cmd,$fields,$cssent,$cscalc);
	}

sub gpsin
        {
        my $done = 0;
        my $buf;

        until ($done)
                {
                ($ct,$in)=$port->read(1);
                $buf .= $in if $ct;
                if ($buf =~ m/\r\n/) { $done = 1;}
                }
        
        return $buf;
        }

--------------ACAA1DB6C13B63F83B235A4F
Content-Type: application/x-perl;
 name="send.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="send.pl"

#!/usr/bin/perl

use FileHandle;
use Device::SerialPort;

$hand=0;

opengps();

sendgps("CMD,VERSION");

$in=gpsin();
($rcmd,$fields,$cs1,$cs2)=decodegps($in);
($pid,$sid,$name) = split ",",$fields;

print STDERR "Connected to $name\nSoftware Ver $sid\n";

sendgps("CMD,HANDON");$hand=1;
#sendgps("CMD,TON");

print STDERR "Uploading Waypoints\n";
#sendgps("CMD,WAYPOINT");

while ($in=<STDIN>)
	{
	chomp $in;

	@wp = split ",",$in;

	$name = shift @wp;
	$lat = 1.0* shift @wp; $lata = shift @wp;
	$lon = 1.0* shift @wp; $lona = shift @wp;
	$alt=shift @wp; $alta=shift @wp;
	$mesg = shift @wp;
	$icon = shift @wp;

        $wpl = sprintf "WPL,%08.3f,%s,%09.3f,%s,%07d,%s,%s,%s,%s",
                $lat,$lata,$lon,$lona,$alt,$alta,$name,$mesg,$icon;
	#printf "waypt %s at %f%s %f%s %f%s mesg %s\n",
	#	$name,$lat,$lata,$lon,$lona,$alt,$alta,$mesg;
        print "$wpl\n";
        sendgps ($wpl);
	}

$port->close;
print STDERR "Done.\n";

sub opengps
        {

        $dev="/dev/ttyS0";
        $quiet=0;
        $lock="/tmp/gps.lock";
        #my $stty=`/bin/stty -g <$dev`;
        
        $port=new Device::SerialPort ($dev,$quiet,$lock)
                || die "Can't open port $dev:$!\n";

        $port->baudrate(4800);
        $port->parity("none");
        $port->databits(8);
        $port->stopbits(1);
        $port->handshake("none");
        $port->are_match("\r\n");
        $port->write_settings;

        print STDERR "Serial port to GPS opened \n";
        } 
sub checksum
	{
	my ($string) = @_;
	my $sum = 0;

	#printf ">>%s<<\n",$string;
	@slist = split (//,$string);
        shift @slist;pop @slist;

	foreach $char (@slist)
		{
		$byte = unpack("C",$char);
		$sum ^= $byte;

		#printf  "c%s b%x s%x\n",$char,$byte,$sum;
		}
        $sumtxt=sprintf "%02x",$sum;
        $sumtxt =~ s/a/A/g;
        $sumtxt =~ s/b/B/g;
        $sumtxt =~ s/c/C/g;
        $sumtxt =~ s/d/D/g;
        $sumtxt =~ s/e/E/g;
        $sumtxt =~ s/f/F/g;

        #print "checksum $sumtxt\n";

	#return $sumtxt;
	return $sum;
	}	

sub sendgps
	{
	my ($cmd) = @_;
	my $mycmd = sprintf "\$PMGN%s*",$cmd;

	$cs = checksum($mycmd);

	$data=sprintf "%s%02X\r\n",$mycmd,$cs;
	$ctout=$port->write($data);
        print "sent $ctout chars in >$data<\n";

	if ($hand && ( $cmd !~ /CSM/))
		{
                $in=gpsin();
		print STDERR "resp $in\n";
		($rcmd,$fields,$cs1,$cs2)=decodegps($in);
		$rcs=hex($fields);
		if (($rcmd !~ /CSM/) || ($rcs != $cs))
			{
                        $port->close;
			die "CS error sending $cmd $fields,$cs\n";
			}
		}

	return $cs;
	}

sub decodegps
	{
	my ($str) = @_;

	#print "recv $str\n";

	$str =~ m/\$PMGN([A-Z][A-Z][A-Z]),(.*)\*([0-9a-fA-F][0-9a-fA-F])/;

	$cmd = $1;
	$fields = $2;
	$cssent = hex($3);

	$cmdstr=sprintf "\$PMGN%s,%s\*",$cmd,$fields;
	$cscalc = checksum($cmdstr);

	if ($cssent != $cscalc)
                {
                $port->close;
	        die "CS error receiving $cmd  $cssent $cscalc\n";
                }
	$hs=sprintf "CSM,%02X",$cscalc;
	sendgps($hs) if $hand && $cmd !~ /CSM/;

	return ($cmd,$fields,$cssent,$cscalc);
	}

sub gpsin
        {
        my $done = 0;
        my $buf;

        until ($done)
                {
                ($ct,$in)=$port->read(1);
                $buf .= $in if $ct;
                if ($buf =~ m/\r\n/) { $done = 1;}
                }
        
        return $buf;
        }

--------------ACAA1DB6C13B63F83B235A4F--



