Show the name and location where every program module was load from. This
is useful for checking where you think you have loaded a .pm file from.
+=== 0^SHOW/QRA <locator> [<locator>]^Show distance between locators
+=== 0^SHOW/QRA <lat> <long>^Convert latitude and longitude to a locator
+This is a multipurpose command that allows you either to calculate the
+distance and bearing between two locators or (if only one locator is
+given on the command line) the distance and beraing from your station
+to the locator. For example:-
+
+SH/QRA IO92QL
+SH/QRA JN06 IN73
+
+The first example will show the distance and bearing to the locator from
+yourself, the second example will calculate the distance and bearing from
+the first locator to the second. You can use 4 or 6 character locators.
+
+It is also possible to convert a latitude and longitude to a locator by
+using this command with a latitude and longitude as an argument, for
+example:-
+
+SH/QRA 52 41 N 0 58 E
+
+=== 0^SHOW/SATELLITE <name> [<hours> <interval>]^Show tracking data
+Show the tracking data from your location to the satellite of your choice
+from now on for the next few hours.
+
+If you use this command without a satellite name it will display a list
+of all the satellites known currently to the system.
+
+If you give a name then you can obtain tracking data of all the passes
+that start and finish 5 degrees below the horizon. As default it will
+give information for the next three hours for every five minute period.
+
+You can alter the number of hours and the step size, within certain
+limits.
+
+Each pass in a period is separated with a row of '-----' characters
+
+So for example:-
+
+SH/SAT AO-10
+SH/SAT FENGYUN1 12 2
+
=== 0^SHOW/SUN [<prefix>|<callsign>]^Show sun rise and set times
Show the sun rise and set times for a (list of) prefixes or callsigns,
together with the azimuth and elevation of the sun currently at those
--- /dev/null
+#
+# load the the keps file after changing it
+#
+my $self = shift;
+return (1, $self->msg('e5')) if $self->priv < 9;
+my @out = Sun::load($self);
+@out = ($self->msg('ok')) if !@out;
+return (1, @out);
my ($self, $line) = @_;
my @list = split /\s+/, $line; # generate a list of callsigns
+return (1, $self->msg('qrashe1')) unless @list > 0;
my @out;
my $fll;
my $fqra = DXBearing::is_qra($list[0]);
my $sqra = $list[0] =~ /^[A-Za-z][A-Za-z]\d\d$/;
my $ll = $line =~ /^\d+\s+\d+\s*[NSns]\s+\d+\s+\d+\s*[EWew]/;
-return (1, $self->msg('qrashe1')) unless @list > 0;
return (1, $self->msg('qrae2', $list[0])) unless $fqra || $sqra || $ll;
+# convert a lat/long into a qra locator
if ($ll) {
my ($llat, $llong) = DXBearing::stoll($line);
return (1, "QRA $line = " . DXBearing::lltoqra($llat, $llong));
}
-#print "$lat $long\n";
+unshift @list, $self->user->qra if @list == 1 && $self->user->qra;
+unshift @list, DXBearing::lltoqra($lat, $long) unless @list > 1;
-my $l = uc $list[0];
-my $f;
+my $f = uc $list[0];
+$f .= 'MM' if $f =~ /^[A-Z][A-Z]\d\d$/;
+($lat, $long) = DXBearing::qratoll($f);
+return (1, $self->msg('qrae2', $list[1])) unless (DXBearing::is_qra($list[1]) || $list[1] =~ /^[A-Za-z][A-Za-z]\d\d$/);
-if (@list > 1) {
- $f = $l;
- $f .= 'MM' if $f =~ /^[A-Z][A-Z]\d\d$/;
- ($lat, $long) = DXBearing::qratoll($f);
- $fll = DXBearing::lltos($lat, $long);
- #print "$lat $long\n";
-
- return (1, $self->msg('qrae2', $list[1])) unless (DXBearing::is_qra($list[1]) || $list[1] =~ /^[A-Za-z][A-Za-z]\d\d$/);
- $l = uc $list[1];
-}
+my $l = uc $list[1];
-$l .= 'MM' if $l =~ /^[A-Z][A-Z]\d\d$/;
-
-my ($qlat, $qlong) = DXBearing::qratoll($l);
-#print "$qlat $qlong\n";
$fll = DXBearing::lltos($lat, $long);
-$fll =~ s/\s+([NSEW])/$1/g;
+my ($qlat, $qlong) = DXBearing::qratoll($l);
$tll = DXBearing::lltos($qlat, $qlong);
+
$tll =~ s/\s+([NSEW])/$1/g;
+$fll =~ s/\s+([NSEW])/$1/g;
my ($b, $dx) = DXBearing::bdist($lat, $long, $qlat, $qlong);
my ($r, $rdx) = DXBearing::bdist($qlat, $qlong, $lat, $long);
#
# show satellite az/el
#
-# 1999/12/9 Steve Franke K9AN
+# copyright (c) 1999 Steve Franke K9AN
#
+# $Id$
#
-my ($self, $satname) = @_;
+my ($self, $line) = @_;
my @out;
-my ($lat, $lon, $alt, $jtime); # lats and longs in radians
-my ($sec, $min, $hr, $day, $mon, $yr) = (gmtime($main::systime))[0,1,2,3,4,5];
-#printf("%2.2d %2.2d %2.2d %2.2d %2.2d\n",$min,$hr,$day,$mon,$yr);
-
-$mon++;
-$yr += 1900;
-$lat=$main::mylatitude;
-$lon=$main::mylongitude;
-$alt=0.0;
-
-$jtime=Sun::Julian_Day($yr,$mon,$day)+$hr/24+$min/60/24;
-($yr,$mon,$day,$hr,$min)=Sun::Calendar_date_and_time_from_JD($jtime);
-#printf("%2.2d %2.2d %2.2d %2.2d %2.2d\n",$min,$hr,$day,$mon,$yr);
-push @out,sprintf("Tracking table for $satname");
-push @out,sprintf("dd/mm UTC Lat Lon Alt(km) Az El Dist(km)");
-my ($slat,$slon,$salt,$az,$el,$distance)=
- Sun::get_satellite_pos(
- $jtime,$lat*$d2r,$lon*$d2r,$alt,$satname);
-push @out,sprintf( # print the current satellite position
- "Now %2.2d:%2.2d %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f",
- $hr,$min,$slat*$r2d,$slon*$r2d,$salt,
- $az*$r2d,$el*$r2d,$distance);
-
-my $numsteps=0;
-my $step = 2; # tracking table resolution in minutes
-$jtime=$jtime+$step/24/60;
-while ( $numsteps < 6*60/$step ) # for now, look 6 hours ahead for tracking table
+my @f = split /\s+/, $line;
+my $satname = uc shift @f;
+my $numhours = shift @f; # the number of hours ahead to print
+my $step = shift @f; # tracking table resolution in minutes
+
+# default hours and step size
+$numhours = 3 unless $numhours && $numhours =~ /^\d+$/;
+$step = 5 unless $step && $step =~ /^\d+$/;
+
+# get nearest lat and long (I can see we will need the altitude here soon as well :-)
+my $lat = $self->user->lat;
+my $lon = $self->user->long;
+my $alt = 0;
+my $call = $self->call;
+unless ($lon || $lat) {
+ $lat = $main::mylatitude;
+ $lon = $main::mylongitude;
+ $call = $main::mycall;
+}
+
+if ($satname && $Sun::keps{$satname}) {
+ my $jtime; # lats and longs in radians
+ my ($sec, $min, $hr, $day, $mon, $yr) = (gmtime($main::systime))[0,1,2,3,4,5];
+ #printf("%2.2d %2.2d %2.2d %2.2d %2.2d\n",$min,$hr,$day,$mon,$yr);
+
+ $mon++;
+ $yr += 1900;
+ $alt=0.0;
+
+ $jtime=Sun::Julian_Day($yr,$mon,$day)+$hr/24+$min/60/24;
+ ($yr,$mon,$day,$hr,$min)=Sun::Calendar_date_and_time_from_JD($jtime);
+ #printf("%2.2d %2.2d %2.2d %2.2d %2.2d\n",$min,$hr,$day,$mon,$yr);
+ push @out, $self->msg("pos", $call, slat($lat), slong($lon));
+ push @out, $self->msg("sat1", $satname, $numhours, $step);
+ push @out, $self->msg("sat2");
+
+ my ($slat,$slon,$salt,$az,$el,$distance)=Sun::get_satellite_pos($jtime,$lat*$d2r,$lon*$d2r,$alt,$satname);
+ # print the current satellite position
+ push @out,sprintf("Now %2.2d:%2.2d %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f",
+ $hr,$min,$slat*$r2d,$slon*$r2d,$salt,
+ $az*$r2d,$el*$r2d,$distance);
+
+ my $numsteps=0;
+ $jtime=$jtime+$step/24/60;
+ my $disc = 0; # discontinuity flag
+ while ( $numsteps < $numhours*60/$step ) # look $numhours ahead for tracking table
{
- my ($yr,$mon,$day,$hr,$min)=Sun::Calendar_date_and_time_from_JD($jtime);
- my ($slat,$slon,$salt,$az,$el,$distance)=
- Sun::get_satellite_pos(
- $jtime,$lat*$d2r,$lon*$d2r,$alt,$satname);
- if( $el*$r2d > -5 ) {
- push @out,sprintf(
- "%2.2d/%2.2d %2.2d:%2.2d %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f",
- $day,$mon,$hr,$min,$slat*$r2d,$slon*$r2d,$salt,
- $az*$r2d,$el*$r2d,$distance);
+ my ($yr,$mon,$day,$hr,$min)=Sun::Calendar_date_and_time_from_JD($jtime);
+ my ($slat,$slon,$salt,$az,$el,$distance)=Sun::get_satellite_pos($jtime,$lat*$d2r,$lon*$d2r,$alt,$satname);
+ if ( $el*$r2d > -5 ) {
+ if ($disc) {
+ $disc = 0;
+ push @out, $self->msg("satdisc");
+ }
+ push @out,sprintf("%2.2d/%2.2d %2.2d:%2.2d %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f",
+ $day,$mon,$hr,$min,$slat*$r2d,$slon*$r2d,$salt,
+ $az*$r2d,$el*$r2d,$distance);
+ } else {
+ $disc++;
+ }
+ $numsteps++;
+ $jtime=$jtime+$step/60/24;
+ }
+} else {
+ push @out, $self->msg("satnf", $satname) if $satname;
+ push @out, $self->msg("sat3");
+ push @out, $self->msg("sat4");
+ my @l;
+ my $i = 0;
+ my $sat;
+ foreach $sat (sort keys %Sun::keps) {
+ if ($i >= 6) {
+ push @out, join ' + ', @l;
+ @l = ();
+ $i = 0;
}
- $numsteps++;
- $jtime=$jtime+$step/60/24;
+ push @l, $sat;
+ $i++;
}
+ push @out, join ' + ', @l;
+}
return (1,@out);
+
+
+
+
+
+
+
+
+
pingi => 'Ping Returned from $_[0] $_[1] (Ave $_[2]) secs',
pinge1 => 'Cannot ping yourself!',
pingint => 'Ping interval on $_[0] set to $_[1] secs',
-
+ pos => 'From Callsign: $_[0] Lat: $_[1] Long: $_[2]',
pr => '$_[0] de $main::mycall $main::cldate $main::ztime >',
pr2 => '($_[0]) de $main::mycall $main::cldate $main::ztime >',
priv => 'Privilege level changed on $_[0]',
read1 => 'Sorry, no new messages for you',
read2 => 'Msg $_[0] not found',
read3 => 'Msg $_[0] not available',
+ sat1 => 'Tracking Table for $_[0] for the next $_[1] hours every $_[2] mins',
+ sat2 => 'dd/mm UTC Lat Lon Alt Km Az El Dist Km',
+ sat3 => 'Syntax: SH/SAT <name> [<hours> <interval>]',
+ sat4 => 'Satellites available:-',
+ satnf => 'Satellite $_[0] unknown',
+ satdisc => '-----',
shutting => '$main::mycall shutting down...',
sloc => 'Cluster lat $_[0] long $_[1], DON\'T FORGET TO CHANGE YOUR DXVars.pm',
snode1 => 'Node Call Sort Version',
@EXPORT = qw($pi $d2r $r2d );
use strict;
-use vars qw($pi $d2r $r2d );
+use vars qw($pi $d2r $r2d);
$pi = 3.141592653589;
$d2r = ($pi/180);
$r2d = (180/$pi);
+use vars qw(%keps);
+use Keps;
+use DXVars;
+use DXUtil;
+
+# reload the keps data
+sub load
+{
+ my @out;
+ my $s = readfilestr("$main::root/local/Keps.pm");
+ if ($s) {
+ eval $s;
+ push @out, $@ if $@;
+ }
+ return @out;
+}
+
sub Julian_Day
{
my $year = shift;
#
#Temporary keps database...
#
-my %keps = (
- noaa15 => {
- number => 25338,
- id => 98030,
- epoch => 99341.00000000,
- mm1 => .00000376,
- mm2 => .00000e-0,
- bstar => .18612e-3,
- inclination => 98.6601,
- raan => 8.2003,
- eccentricity => .0011401,
- argperigee => 112.4684,
- meananomaly => 42.5140,
- meanmotion => 14.23047277081382,
- },
- tdrs5 => {
- number => 21639,
- id => 91054,
- epoch => 99341.34471854,
- mm1 => .00000095,
- mm2 => .00000e-0,
- bstar => .10000e-3,
- inclination => 1.5957,
- raan => 88.4884,
- eccentricity => .003028,
- argperigee => 161.6582,
- meananomaly => 135.4323,
- meanmotion => 1.00277774,
- },
- oscar16 => {
- number => 20439,
- id => 90005,
- epoch => 99341.14501399,
- mm1 => .00000343,
- mm2 => .00000e-0,
- bstar => .14841e-3,
- inclination => 98.4690,
- raan => 55.0032,
- eccentricity => .0012163,
- argperigee => 66.4615,
- meananomaly => 293.7842,
- meanmotion => 14.303202855,
- },
-);
my $jtime = shift;
my $lat = shift;
my $lon = shift;
$yr = $c-4715 if( $mon == 1 || $mon == 2 );
$hr = int($frac*24);
$min= int(($frac*24 - $hr)*60+0.5);
+ if ($min == 60) { # this may well prove inadequate DJK
+ $hr += 1;
+ $min = 0;
+ }
return ($yr,$mon,$day,$hr,$min);
}
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Convert an Amsat 2 line keps bull into Sun.pm format
+#
+# This program will accept on stdin a standard AMSAT 2 line keps
+# bull such as you would find in an email or from the packet network
+#
+# It will write a file called /spider/local/Keps.pm, this means that
+# the latest version will be read in every time you restart the
+# cluster.pl. You can also call Sun::load from a cron line if
+# you like to re-read it automatically.
+#
+# This program is designed to be called from /etc/aliases or
+# a .forward file so you can get yourself on the keps mailing
+# list from AMSAT and have the keps updated automatically once
+# a week.
+#
+# I will distribute the latest keps with every patch but you can
+# get your own data from:
+#
+# http://www.amsat.org/amsat/ftp/keps/current/nasa.all
+#
+# Copyright (c) 2000 Dirk Koopman G1TLH
+#
+# $Id$
+#
+
+require 5.004;
+
+# search local then perl directories
+BEGIN {
+ # root of directory tree for this system
+ $root = "/spider";
+ $root = $ENV{'DXSPIDER_ROOT'} if $ENV{'DXSPIDER_ROOT'};
+
+ unshift @INC, "$root/perl"; # this IS the right way round!
+ unshift @INC, "$root/local";
+}
+
+use strict;
+use Data::Dumper;
+
+use vars qw($root);
+
+my $fn = "$root/local/Keps.pm";
+my $state = 0;
+my $name;
+my %keps;
+my $ref;
+my $line;
+
+while (<STDIN>) {
+ ++$line;
+ chomp;
+ s/^\s+//;
+ s/\s+$//;
+ next unless $_;
+ last if m{^/EX}i;
+ last if m{^-};
+
+ if ($state == 0 && /^TO ALL/) {
+ $state = 1;
+ } elsif ($state == 1) {
+ last if m{^/EX/i};
+
+ if (/^\w+/) {
+ s/\s/-/g;
+ $name = $_;
+ $ref = $keps{$name} = {};
+ $state = 2;
+ }
+ } elsif ($state == 2) {
+ if (/^1 /) {
+ my ($id, $number, $epoch, $decay, $mm2, $bstar, $elset) = unpack "xxa5xxa5xxxa15xa10xa8xa8xxxa4x", $_;
+ $ref->{id} = $id - 0;
+ $ref->{number} = $number - 0;
+ $ref->{epoch} = $epoch - 0;
+ $ref->{mm1} = $decay - 0;
+ $ref->{mm2} = genenum($mm2);
+ $ref->{bstar} = genenum($bstar);
+ $ref->{elset} = $elset - 0;
+# print "$id $number $epoch $decay $mm2 $bstar $elset\n";
+# print "mm2: $ref->{mm2} bstar: $ref->{bstar}\n";
+
+ $state = 3;
+ } else {
+ print "out of order on line $line\n";
+ undef $ref;
+ delete $keps{$name};
+ $state = 1;
+ }
+ } elsif ($state == 3) {
+ if (/^2 /) {
+ my ($id, $incl, $raan, $ecc, $peri, $man, $mmo, $orbit) = unpack "xxa5xa8xa8xa7xa8xa8xa11a5x", $_;
+ $ref->{meananomaly} = $man - 0;
+ $ref->{meanmotion} = $mmo - 0;
+ $ref->{inclination} = $incl - 0;
+ $ref->{eccentricity} = ".$ecc" - 0;
+ $ref->{argperigee} = $peri - 0;
+ $ref->{raan} = $raan - 0;
+ $ref->{orbit} = $orbit - 0;
+ } else {
+ print "out of order on line $line\n";
+ delete $keps{$name};
+ }
+ undef $ref;
+ $state = 1;
+ }
+}
+
+my $dd = new Data::Dumper([\%keps], [qw(*keps)]);
+$dd->Indent(1);
+$dd->Quotekeys(0);
+open(OUT, ">$fn") or die "$fn $!";
+print OUT "#\n# this file is automatically produced by convkeps.pl\n#\n";
+print OUT "\npackage Sun;\n\n";
+print OUT $dd->Dumpxs;
+print OUT "\n";
+close(OUT);
+
+
+# convert (+/-)00000-0 to (+/-).00000e-0
+sub genenum
+{
+ my ($sign, $frac, $esign, $exp) = unpack "aa5aa", shift;
+ my $n = $sign . "." . $frac . 'e' . $esign . $exp;
+ return $n - 0;
+}
+