Inserting Live Tracks Into APRS

Scripts

These scripts were created to route non-aprs telemetry from a high altitude balloon into the aprs-is system. The balloon these were created for had an aprs, spot, and cellular tracking system.

To insert the tracking data into the APRS-IS system you need to run the script on a computer with an Internet connection. The scripts are very Alpha and will most likely break if they encounter anything unexpected. I am also a little embarrassed about my code, it's not very elegant.

Spot

GeSHi © 2004-2007 Nigel McNie, 2007-2010 Benny Baumann, 2008-2009 Milian Wolff
  1. #!/usr/bin/perl
  2. # GPLv3 Matt Skorina May 2011
  3. # Converts SPOT Tracker position to APRS format and sends it to APRS-IS.
  4.  
  5. # Make sure you clear previous tracks before starting.
  6.  
  7. # Currently this will not work if there is only 1 entry in the XML feed
  8. # http://www.nntp.perl.org/group/perl.beginners/2007/04/msg90658.html
  9. # says the only solution is to check, or to not use XML::Simple.
  10. # Also we can just leave some enteries in the XML feed and the latest
  11. # will be beaconed to APRS when the script is started, which would
  12. # probably be okay
  13.  
  14. $spot_id = "<SPOT API KEY>"; # Shared key for SPOT device
  15. $check_interval = 60; # How often to check for new data (seconds)
  16. $spot_callsign = "KF7DXI-12"; # Callsign of beacon
  17. $spot_symbol = "/I"; # /I = TCPIP Internet Station
  18. $software = "SPOT01"; # Digipath for SPOT position
  19. $comment = "*TESTING* SPOT Tracker"; # Comment for message in addition to time stamp
  20.  
  21. use LWP::Simple;
  22. use XML::Simple;
  23. use Ham::APRS::FAP;
  24. use IO::Socket;
  25.  
  26. $last_packet = "";
  27. $spot_url = "http://share.findmespot.com/messageService/guestlinkservlet?glId=$spot_id&completeXml=true";
  28.  
  29. while(1==1) {
  30. $spot_data = get($spot_url);
  31. $xml = new XML::Simple;
  32. $spot_xml = $xml->XMLin("$spot_data");
  33.  
  34. print @spot_xml;
  35.  
  36. if ($spot_xml->{totalCount} != 0) {
  37. $latitude = "$spot_xml->{message}->[0]->{latitude}";
  38. $longitude = "$spot_xml->{message}->[0]->{longitude}";
  39. $time = "$spot_xml->{message}->[0]->{timeInGMTSecond}";
  40.  
  41. $timestamp = Ham::APRS::FAP::make_timestamp($time,0);
  42. $position = Ham::APRS::FAP::make_position($latitude,$longitude,-1,0,-10000,$spot_symbol,0,0);
  43.  
  44. $packet = "$spot_callsign>$software,TCPIP*:=$position$timestamp $comment";
  45.  
  46. if ($packet ne $last_packet) {
  47.         print "$packet\n";
  48.  
  49.   my $sock = new IO::Socket::INET (
  50.     PeerAddr => '64.89.177.168',
  51.     PeerPort => '14580',
  52.     Proto => 'tcp',
  53.   );
  54.   die "Could not connect to server: $!\n" unless $sock;
  55.   print $sock "user KF7DXI-2 pass 22441\n";
  56.   print $sock "$packet\n";
  57.   close($sock);
  58.  
  59.         $last_packet = $packet;
  60. }
  61. }
  62. sleep($check_interval);
  63. print "Done\n";
  64. }
Parsed in 0.019 seconds at 106.38 KB/s

Instamapper

GeSHi © 2004-2007 Nigel McNie, 2007-2010 Benny Baumann, 2008-2009 Milian Wolff
  1. #!/usr/bin/perl
  2. # GPLv3 Matt Skorina May 2011
  3. # This script will scrape the API of the Instamapper (instamapper.com)
  4. # cellular tracking service and send position reports to APRS-IS to be
  5. # collected by any APRS internet connected client.
  6.  
  7. # Make sure you clear previous tracks before starting.
  8.  
  9. # Running a test for several hours we had the script fail after awhile
  10. # with an error of "malformed JSON string, neither array, object,..."
  11. # which failed on the "$decode = decode_json($raw);" line
  12. # I don't know the input that caused the error but we need the script to
  13. # keep going in the event of non-parasable errors because we can't
  14. # restart it in the field. Or we need to be able to restart it in the
  15. # field.
  16.  
  17. $api_key = "<INSTAMAPPER API KEY>";
  18. $check_interval = 5; # How long to wait between checks, minimum per API terms is 10s
  19. $igate = "<VAID CALLSIGN>"; # Callsign to gate packet to APRS-IS
  20. $pass = "<APRS PASSCODE>"; # APRS passcode for igate callsign (passcode CALLSIGN on *nix systems)
  21. $aprs_server = "64.89.177.168"; # APRS-IS server to connect to
  22. $aprs_port = "14580"; # Port of APRS-IS server normally 14580
  23. $callsign = "<VALID CALLSIGN>"; # Callsign for cellular tracker
  24. $software = "INSTAM"; # What type of device this is
  25. $symbol = "/I"; # APRS symbol, /I is TCPIP
  26. $comment = "Balloon Cell Tracker"; # APRS comment, so people know what this is
  27.  
  28. use LWP::Simple;
  29. use JSON;
  30. use Ham::APRS::FAP;
  31. use IO::Socket;
  32.  
  33. $last_packet = "";
  34. $url = "http://www.instamapper.com/api?action=getPositions&key=$api_key&format=json";
  35.  
  36. while (1==1) { # There is probably a better way to do this...
  37. $raw = get($url);
  38. $decode = decode_json($raw);
  39.  
  40. $latitude = $decode->{positions}->[0]->{latitude};
  41. $longitude = $decode->{positions}->[0]->{longitude};
  42. $altitude = $decode->{positions}->[0]->{altitude};
  43. $speed_meter = $decode->{positions}->[0]->{speed}; # Instamapper gives speed in m/s
  44. $speed_kph = $speed_meter*3.6; # APRS wants speed in kph
  45. $course = $decode->{positions}->[0]->{heading};
  46. $time = $decode->{positions}->[0]->{timestamp};
  47.  
  48. $timestamp = Ham::APRS::FAP::make_timestamp($time,0); # To double check time, probably a better way to do this
  49. $position = Ham::APRS::FAP::make_position($latitude,$longitude,$speed_kph,$course,$altitude,$symbol,0,0);
  50.  
  51. $packet = "$callsign>$software,TCPIP*:=$position$timestamp $comment";
  52.  
  53. if ($packet ne $last_packet) {
  54.   print "$packet\n"; # So you can see what's going on
  55.  
  56.   $sock = new IO::Socket::INET ( # One time connection to server for each packet
  57.     PeerAddr => "$aprs_server",
  58.     PeerPort => "$aprs_port",
  59.     Proto => "tcp",
  60.   );
  61.   die "Could not connect to server\n" unless $sock;
  62.   print $sock "user $igate pass $pass\n";
  63.   print $sock "$packet\n";
  64.   close($sock);
  65.  
  66.   $last_packet = $packet; # So we don't send duplicate packets
  67. }
  68. sleep($check_interval); # So we don't swamp the API
  69. print "Done\n";
  70. }
Parsed in 0.023 seconds at 126.22 KB/s

About

Matt Skorina is a freshman Electrical Engineering student. more...

Projects Menu