Order Tray | Contact Us | Home | SIG Lists

[aprssig] Small PC program to send APRS location via Internet

Arne Stahre sm6vyf at gatugarden.com
Sun Oct 2 18:13:59 UTC 2005


  Hi!

  This is relatively small (except that you'll need perl - 
http://www.perl.org/ or http://aspn.activestate.com/ASPN/).
  Somewhat tested with Linux and Windows 2000.

  73 de SM6VYF/Arne

#!/usr/bin/perl -w
# 2005-10-02 de SM6VYF/Arne
use strict;
use Socket;

our $PROGNAME = 'SmallPC';
our $PROGVERSION = '0.9';

our $HOST = 'northwest.aprs2.net', # cf. http://www.aprs2.net/
our $PORT = 14580,                 # cf. http://www.aprs2.net/
our $TTY = '/dev/ttyS0';           # or, e.g., 'COM1' for Windows

our ($CALL, $TABLE, $SYMBOL, $COMMENT) = ('MYCALL', '/', '-', "$PROGNAME 
$PROGVERSION");
our $INTERVAL = 30;

our $DEBUG = 1;

our $TIMEOUT = 10;

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

   my ($cs, $i, $sum);

   if ($str =~ /\$(.*?)\*([0-9A-F]{2})/) {
     $str = $1;
     $cs = hex($2);
     $sum = 0;
     for ($i = 0; $i < length($str); $i += 1) {
       $sum ^= ord(substr($str, $i, 1));
     }
     return ($cs == $sum);
   }
   return 0;
}

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

   if (my ($hour, $min, $sec, $statc,
	  $lat, $latmin, $latc,
	  $lon, $lonmin, $lonc,
	  $sog, $tmg,
	  $day, $month, $year) =
       ($str =~ m/\$GPRMC,(\d{2})(\d{2})(\d{2})\.\d+,(.),
                  (\d{2})(\d+\.\d*),(.),
                  (\d{3})(\d+\.\d*),(.),
                  (\d+\.\d*),(\d+\.\d*),
                  (\d{2})(\d{2})(\d{2})/x)) {
      if ($statc eq 'A') {
        if (nmea_checksum($str)) {
	return (sprintf('%02d%05.2f%s', $lat, $latmin, $latc),
		sprintf('%03d%05.2f%s', $lon, $lonmin, $lonc),
		sprintf('%02d%02d%02d', $day, $hour, $min),
		sprintf('%03d', $tmg),
		sprintf('%03d', $sog));
        }
      }
    }
    return ();
}

sub aprspass {
    my ($call) = @_;

    $call =~ m/([^\-]+)/i;	# skip SSID
    my @call = split(//, $1);
    my $hash = 0x73e2;
    for (my $i = 0; $i < $#call; $i += 2) {
      $hash ^= ord($call[$i]) << 8;
      $hash ^= ord($call[$i + 1]);
    }
    return $hash;
}

my $proto = getprotobyname('tcp');
socket(\*H, AF_INET, SOCK_STREAM, $proto) or die "socket:$!";
my $in_addr = (gethostbyname($HOST))[4];
my $addr = sockaddr_in($PORT, $in_addr);
connect(\*H, $addr) or die "connect:$!";

my $pass = aprspass("$CALL");
syswrite(\*H, "user $CALL pass $pass vers $PROGNAME $PROGVERSION\r");
sleep(1);

my $nmea;
my $timestamp = 0;

system("stty 4800 -echo -cstopb raw < $TTY") if $^O eq 'linux';
if (open(GPS, "+<$TTY")) {
    my $running = 1;

    $SIG{INT} = sub { $running = 0 };

    while ($running) {
      eval {
        local $SIG{ALRM} = sub { die "alarm\n" };
        alarm($TIMEOUT);
        $nmea = <GPS>;
        alarm(0);
      };
      if ($@) {
        die unless $@ eq "alarm\n";
      } elsif (! $nmea) {
        $running = 0;
      } elsif (length $nmea ne 0) {
        if (time() - $timestamp > $INTERVAL) {
	 my ($lat, $lon, $time, $cse, $spd) = parse_rmc($nmea);
	 if ($lat && $lon) {
	   my $beacon = 
"$CALL>APZ001,TCPIP:/${time}z$lat$TABLE$lon$SYMBOL$cse/$spd $COMMENT";
	   print "$beacon\n" if $DEBUG;
	   syswrite(\*H, "$beacon\r");
	   $timestamp = time();
	 }
        }
      }
      print " $nmea" if $DEBUG;
    }
    close(GPS);
}

close(\*H);




More information about the aprssig mailing list