Astro-SpaceTrack
view release on metacpan or search on metacpan
lib/Astro/SpaceTrack.pm view on Meta::CPAN
visible => {
favorite => 'Visible',
name => 'Visible satellites',
tle => {
EPOCH => '>now-30',
},
# number => 21,
},
special => {
favorite => 'Special_interest',
name => 'Special interest satellites',
tle => {
EPOCH => '>now-30',
},
# number => 23,
},
bright_geosynchronous => {
favorite => 'brightgeo',
name => 'Bright Geosynchronous satellites',
tle => {
EPOCH => '>now-30',
},
},
human_spaceflight => {
favorite => 'human_spaceflight',
name => 'Human Spaceflight',
tle => {
EPOCH => '>now-30',
},
},
# Added by TRW
payloads => {
name => 'All payloads',
# satcat => {
# OBJECT_TYPE => 'PAYLOAD',
# },
tle => {
EPOCH => '>now-30',
OBJECT_TYPE => 'payload',
},
},
},
],
);
my %mutator = ( # Mutators for the various attributes.
addendum => \&_mutate_attrib, # Addendum to banner text.
banner => \&_mutate_attrib,
cookie_expires => \&_mutate_spacetrack_interface,
cookie_name => \&_mutate_spacetrack_interface,
domain_space_track => \&_mutate_spacetrack_interface,
dump_headers => \&_mutate_dump_headers, # Dump all HTTP headers. Undocumented and unsupported.
fallback => \&_mutate_attrib,
filter => \&_mutate_attrib,
identity => \&_mutate_identity,
iridium_status_format => \&_mutate_iridium_status_format,
max_range => \&_mutate_number,
password => \&_mutate_authen,
pretty => \&_mutate_attrib,
prompt => \&_mutate_attrib,
scheme_space_track => \&_mutate_attrib,
session_cookie => \&_mutate_spacetrack_interface,
space_track_version => \&_mutate_space_track_version,
url_iridium_status_kelso => \&_mutate_attrib,
url_iridium_status_mccants => \&_mutate_attrib,
url_iridium_status_sladen => \&_mutate_attrib,
username => \&_mutate_authen,
verbose => \&_mutate_attrib,
verify_hostname => \&_mutate_verify_hostname,
webcmd => \&_mutate_attrib,
with_name => \&_mutate_attrib,
);
my %accessor = (
cookie_expires => \&_access_spacetrack_interface,
cookie_name => \&_access_spacetrack_interface,
domain_space_track => \&_access_spacetrack_interface,
session_cookie => \&_access_spacetrack_interface,
);
foreach my $key ( keys %mutator ) {
exists $accessor{$key}
or $accessor{$key} = sub {
$_[0]->_deprecation_notice( attribute => $_[1] );
return $_[0]->{$_[1]};
};
}
# Maybe I really want a cookie_file attribute, which is used to do
# $self->{agent}->cookie_jar ({file => $self->{cookie_file}, autosave => 1}).
# We'll want to use a false attribute value to pass an empty hash. Going to
# this may imply modification of the new () method where the cookie_jar is
# defaulted and the session cookie's age is initialized.
=item $st = Astro::SpaceTrack->new ( ... )
=for html <a name="new"></a>
This method instantiates a new Space-Track accessor object. If any
arguments are passed, the C<set()> method is called on the new object,
and passed the arguments given.
For both historical and operational reasons, this method can get the
C<username> and C<password> values from multiple locations. It uses the
first defined value it finds in the following list:
=over
=item a value explicitly specified as an argument to C<new()>;
=item a value from the L<IDENTITY FILE|/IDENTITY FILE>, if the
C<identity> attribute is explicitly specified as true and
L<Config::Identity|Config::Identity> is installed;
=item a value from environment variable C<SPACETRACK_USER> if that has a
non-empty value;
=item a value from the L<IDENTITY FILE|/IDENTITY FILE>, if the
C<identity> attribute defaulted to true and
L<Config::Identity|Config::Identity> s installed;
=item a value from environment variable C<SPACETRACK_OPT>.
=back
The reason for preferring C<SPACETRACK_USER> over an identity file value
taken by default is that I have found that under Mac OS X an SSH session
does not have access to the system keyring, and
L<Config::Identity|Config::Identity> provides no other way to specify
the passphrase used to decrypt the private key. I concluded that if the
user explicitly requested an identity that it should be preferred to
anything from the environment, but that, for SSH access to be usable, I
needed to provide a source of username and password that would be taken
before the L<IDENTITY FILE|/IDENTITY FILE> was tried by default.
Proxies are taken from the environment if defined. See the ENVIRONMENT
section of the Perl LWP documentation for more information on how to
set these up.
=cut
sub new {
my ( $class, %arg ) = @_;
$class = ref $class if ref $class;
my $self = {
banner => 1, # shell () displays banner if true.
dump_headers => DUMP_NONE, # No dumping.
fallback => 0, # Do not fall back if primary source offline
filter => 0, # Filter mode.
iridium_status_format => 'kelso',
max_range => 500, # Sanity limit on range size.
password => undef, # Login password.
pretty => 0, # Pretty-format content
prompt => 'SpaceTrack> ',
scheme_space_track => 'https',
_space_track_interface => [
undef, # No such thing as version 0
undef, # Interface version 1 retured.
{ # Interface version 2
# This interface does not seem to put an expiration time
# on the cookie. But the docs say it's only good for a
# couple hours, so we need this so we can fudge
# something in when the time comes.
cookie_expires => 0,
cookie_name => 'chocolatechip',
domain_space_track => 'www.space-track.org',
session_cookie => undef,
},
],
space_track_version => DEFAULT_SPACE_TRACK_VERSION,
url_iridium_status_kelso =>
'https://celestrak.org/SpaceTrack/query/iridium.txt',
url_iridium_status_sladen =>
'http://www.rod.sladen.org.uk/iridium.htm',
username => undef, # Login username.
verbose => undef, # Verbose error messages for catalogs.
verify_hostname => 1, # Don't verify host names by default.
webcmd => undef, # Command to get web help.
with_name => undef, # True to retrieve three-line element sets.
};
bless $self, $class;
$self->set( identity => delete $arg{identity} );
$ENV{SPACETRACK_OPT} and
$self->set (grep {defined $_} split '\s+', $ENV{SPACETRACK_OPT});
# TODO this makes no sense - the first branch of the if() can never
# be executed because I already deleted $arg{identity}. But I do not
# want to execute the SPACETRACK_USER code willy-nilly -- maybe warn
# if identity is 1 and I don't have both a username and a password.
if ( defined( my $id = delete $arg{identity} ) ) {
$self->set( identity => $id );
} elsif ( $ENV{SPACETRACK_USER} ) {
my ($user, $pass) = split qr{ [:/] }smx, $ENV{SPACETRACK_USER}, 2;
'' ne $user
and '' ne $pass
or $user = $pass = undef;
$self->set (username => $user, password => $pass);
} else {
$self->set( identity => undef );
}
defined $ENV{SPACETRACK_VERIFY_HOSTNAME}
and $self->set( verify_hostname =>
$ENV{SPACETRACK_VERIFY_HOSTNAME} );
keys %arg
and $self->set( %arg );
return $self;
}
=for html <a name="amsat"></a>
lib/Astro/SpaceTrack.pm view on Meta::CPAN
{
local $" = ''; # Make "@a" equivalent to join '', @a.
$rslt->content( join '',
map { "@$_\n" }
sort { $a->[0] <=> $b->[0] }
@lines
);
}
$self->__dump_response( $rslt );
return;
},
},
time => {
before => sub {
my ( undef, $context ) = @_; # Invocant unused
eval {
require Time::HiRes;
$context->{start_time} = Time::HiRes::time();
1;
} or warn 'No timings available. Can not load Time::HiRes';
return;
},
after => sub {
my ( undef, $context ) = @_; # Invocant unused
$context->{start_time}
and warn sprintf "Elapsed time: %.2f seconds\n",
Time::HiRes::time() - $context->{start_time};
return;
}
},
);
my $readline_word_break_re;
{
my %alias = (
show => 'get',
);
sub _verb_alias {
my ( $verb ) = @_;
return $alias{$verb} || $verb;
}
}
sub shell {
my @args = @_;
my $self = _instance( $args[0], __PACKAGE__ ) ? shift @args :
Astro::SpaceTrack->new (addendum => <<'EOD');
'help' gets you a list of valid commands.
EOD
my $stdout = \*STDOUT;
my $read;
unshift @args, 'banner' if $self->{banner} && !$self->{filter};
# Perl::Critic wants IO::Interactive::is_interactive() here. But
# that assumes we're using the *ARGV input mechanism, which we're
# not (command arguments are SpaceTrack commands.) Also, we would
# like to be prompted even if output is to a pipe, but the
# recommended module calls that non-interactive even if input is
# from a terminal. So:
my $interactive = -t STDIN;
while (1) {
my $buffer;
if (@args) {
$buffer = shift @args;
} else {
$read ||= $interactive ? ( eval {
$self->_get_readline( $stdout )
} || sub { print { $stdout } $self->getv( 'prompt' ); return <STDIN> } ) :
sub { return<STDIN> };
$buffer = $read->();
}
last unless defined $buffer;
$buffer =~ s/ \A \s+ //smx;
$buffer =~ s/ \s+ \z //smx;
next unless $buffer;
next if $buffer =~ m/ \A [#] /smx;
# Break the buffer up into tokens, but leave quotes and escapes
# in place, so that (e.g.) '\>foo' is seen as an argument, not a
# redirection.
my @cmdarg = Text::ParseWords::parse_line( '\s+', 1, $buffer );
# Pull off any redirections.
my $redir = '';
@cmdarg = map {
m/ \A > /smx ? do {$redir = $_; ()} :
$redir =~ m/ \A >+ \z /smx ? do {$redir .= $_; ()} :
$_
} @cmdarg;
# Rerun everything through parse_line again, but with the $keep
# argument false. This should not create any more tokens, it
# should just un-quote and un-escape the data.
@cmdarg = map { Text::ParseWords::parse_line( qr{ \s+ }, 0, $_ ) } @cmdarg;
$redir ne ''
and ( $redir ) = Text::ParseWords::parse_line ( qr{ \s+ }, 0, $redir );
$redir =~ s/ \A (>+) ~ /$1$ENV{HOME}/smx;
my $verb = lc shift @cmdarg;
my %meta_command = (
before => [],
after => [],
);
while ( my $def = $known_meta{$verb} ) {
my %context;
foreach my $key ( qw{ before after } ) {
$def->{$key}
or next;
push @{ $meta_command{$key} }, sub {
return $def->{$key}->( $self, \%context, @_ );
};
}
$verb = shift @cmdarg;
}
last if $verb eq 'exit' || $verb eq 'bye';
$verb = _verb_alias( $verb );
$verb eq 'source' and do {
eval {
splice @args, 0, 0, $self->_source (shift @cmdarg);
1;
} or warn ( $@ || 'An unknown error occurred' ); ## no critic (RequireCarping)
lib/Astro/SpaceTrack.pm view on Meta::CPAN
} else {
eval {
$rslt = $self->$verb (@cmdarg);
1;
} or do {
warn $@; ## no critic (RequireCarping)
next;
};
}
foreach my $pseudo ( reverse @{ $meta_command{after} } ) {
$pseudo->( $rslt );
}
if ( ARRAY_REF eq ref $rslt ) {
foreach (@$rslt) {print { $out } "$_\n"}
} elsif ( ! ref $rslt ) {
print { $out } "$rslt\n";
} elsif ($rslt->is_success) {
$self->content_type()
or not $self->{filter}
or next;
my $content = $rslt->content;
chomp $content;
print { $out } "$content\n";
} else {
my $status = $rslt->status_line;
chomp $status;
warn $status, "\n";
$rslt->code() == HTTP_I_AM_A_TEAPOT
and print { $out } $rslt->content(), "\n";
}
}
$interactive
and not $self->{filter}
and print { $stdout } "\n";
return;
}
sub _get_readline { ## no critic (Subroutines::RequireArgUnpacking)
my ( $self ) = @_;
require Term::ReadLine;
$rdln ||= Term::ReadLine->new (
'SpaceTrack orbital element access');
@_ > 1
and $_[1] = ( $rdln->OUT || \*STDOUT ); # $stdout
if ( 'Term::ReadLine::Perl' eq $rdln->ReadLine() ) {
require File::Glob;
$readline_word_break_re ||= qr<
[\Q$readline::rl_completer_word_break_characters\E]+
>smx;
no warnings qw{ once };
$readline::rl_completion_function = sub {
my ( $text, $line, $start ) = @_;
return $self->__readline_completer(
$text, $line, $start );
};
}
return sub { $rdln->readline ( $self->getv( 'prompt' ) ) };
}
=for html <a name="source"></a>
=item $st->source ($filename);
This convenience method reads the given file, and passes the individual
lines to the shell method. It croaks if the file is not provided or
cannot be read.
=cut
# We really just delegate to _source, which unpacks.
sub source {
my $self = _instance( $_[0], __PACKAGE__ ) ? shift :
Astro::SpaceTrack->new ();
$self->shell ($self->_source (@_), 'exit');
return;
}
=for html <a name="spacetrack"></a>
=item $resp = $st->spacetrack ($name);
This method returns predefined sets of data from the Space Track web
site, using either canned queries or global favorites.
The following catalogs are available:
Name Description
full Full catalog
payloads All payloads
* navigation Navigation satellites
* weather Weather satellites
geosynchronous Geosynchronous bodies
iridium Iridium satellites
orbcomm OrbComm satellites
globalstar Globalstar satellites
intelsat Intelsat satellites
inmarsat Inmarsat satellites
* amateur Amateur Radio satellites
* visible Visible satellites
* special Special satellites
* bright_geosynchronous
Bright Geosynchronous satellites
* human_spaceflight
Human Spaceflight
well_tracked_objects
Well-Tracked Objects not associated
with a specific launch
The starred items are 404 as of 2026-01-19. They are deprecated and will
be removed.
The following option is supported:
-json
specifies the TLE be returned in JSON format
lib/Astro/SpaceTrack.pm view on Meta::CPAN
identity file is encrypted C<gpg2> must be installed and properly
configured. See L<IDENTITY FILE|/IDENTITY FILE> below for details of the
identity file.
I have found that C<gpg> does not seem to work nicely, even though
L<Config::Identity|Config::Identity> prefers it to C<gpg2> if both are
present. The L<Config::Identity|Config::Identity> documentation says
that you can override this by setting environment variable C<CI_GPG>
to the executable you want used.
If this attribute is unspecified (to C<new()> or specified as C<undef>
(to C<new()> or C<set()>), the value of environment variable
C<SPACETRACK_IDENTITY> will be used as the new value.
When a new object is instantiated, the identity is processed first; in
this way attribute values that come from the environment or are
specified explicitly override those that come from the identity file. If
you explicitly set this on an already-instantiated object, the attribute
values from the identity file will replace those in the object.
When you instantiate an object, the identity from environment variable
C<SPACETRACK_USER> will be preferred over the value from the identity
file, if any, even if the C<identity> attribute is explicitly set true.
=item iridium_status_format (string)
This attribute specifies the default format of the data returned by the
C<iridium_status()> method. Valid values are 'kelso', 'sladen' or
'spacetrack'. See that method for more information.
As of version 0.100_02, the default is C<'kelso'>. It used to be
C<'mccants'>, but Mike McCants no longer maintains his Iridium status
web page, and format C<'mccants'> was removed as of version 0.137.
This attribute is B<deprecated>.
=item max_range (number)
This attribute specifies the maximum size of a range of NORAD IDs to be
retrieved. Its purpose is to impose a sanity check on the use of the
range functionality.
The default is 500.
=item password (text)
This attribute specifies the Space-Track password.
The default is an empty string.
=item pretty (Boolean)
This attribute specifies whether the content of the returned
L<HTTP::Response|HTTP::Response> is to be pretty-formatted. Currently
this only applies to Space Track data returned in C<JSON> format.
Pretty-formatting the C<JSON> is extra overhead, so unless you intend to
read the C<JSON> yourself this should probably be false.
The default is C<0> (i.e. false).
=item prompt (string)
This attribute specifies the prompt issued by the C<shell()> method. The
default is C<< 'SpaceTrack> ' >>.
=item scheme_space_track (string)
This attribute specifies the URL scheme used to access the Space Track
web site. The user will not normally need to modify this, but if the web
site changes schemes for some reason, this attribute may provide a way
to get queries going again.
The default is C<'https'>.
=item session_cookie (text)
This attribute specifies the session cookie. You should only set it
with a previously-retrieved value.
The default is an empty string.
=item space_track_version (integer)
This attribute specifies the version of the Space Track interface to use
to retrieve data. The only valid value is C<2>. If you set it to a
false value (i.e. C<undef>, C<0>, or C<''>) it will be set to the
default.
The default is C<2>.
=item url_iridium_status_kelso (text)
This attribute specifies the location of the celestrak.org Iridium
information. You should normally not change this, but it is provided
so you will not be dead in the water if Dr. Kelso needs to re-arrange
his web site.
The default is 'https://celestrak.org/SpaceTrack/query/iridium.txt'
This attribute is B<deprecated>.
=item url_iridium_status_mccants (text)
This attribute is B<deprecated>, and any access of it will be fatal.
=item url_iridium_status_sladen (text)
This attribute specifies the location of Rod Sladen's Iridium
Constellation Status page. You should normally not need to change this,
but it is provided so you will not be dead in the water if Mr. Sladen
needs to change his ISP or re-arrange his web site.
The default is 'http://www.rod.sladen.org.uk/iridium.htm'.
This attribute is B<deprecated>.
=item username (text)
This attribute specifies the Space-Track username.
The default is an empty string.
=item verbose (Boolean)
( run in 0.868 second using v1.01-cache-2.11-cpan-0b5f733616e )