| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# ABSTRACT: Interface with the ADSBExchange API |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
WebService::ADSBExchange |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use WebService::ADSBExchange; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $adsb = WebService::ADSBExchange->new( key => $key ); |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $registration = 'N161UW'; |
|
15
|
|
|
|
|
|
|
my $position = $adsb->single_aircraft_position_by_registration($registration); |
|
16
|
|
|
|
|
|
|
my $latitude = $position->{ac}[0]->{lat}; |
|
17
|
|
|
|
|
|
|
my $longitude = $position->{ac}[0]->{lon}; |
|
18
|
|
|
|
|
|
|
my $flight = $position->{ac}[0]->{flight}; |
|
19
|
|
|
|
|
|
|
say "$registration is flight $flight and its current position is $latitude by $longitude"; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
This interface helps the user to communicate with the API at adsbexchange.com to track aircraft |
|
24
|
|
|
|
|
|
|
information. The API could be used, for example, to alert you when an aircraft is within four |
|
25
|
|
|
|
|
|
|
miles and flying under 5000 feet, or when an aircraft squawks 7700. To use the API you need to |
|
26
|
|
|
|
|
|
|
register at https://rapidapi.com/adsbx/api/adsbexchange-com1 and buy a subscription. |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
To use the module, you first create a WebService::ADSBExchange object. The new() function takes |
|
29
|
|
|
|
|
|
|
one parameter: your API Key. |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $adsb = WebService::ADSBExchange->new( key => $key ); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
... and then you are ready to use the methods on your $adsb object. If you send no key you will |
|
34
|
|
|
|
|
|
|
get an error message from the module. If you send an invalid key, the module will use it and |
|
35
|
|
|
|
|
|
|
you'll get an error from the API. |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
The API URL is fixed in the module, but if it changes you can also pass the new one to the new() |
|
38
|
|
|
|
|
|
|
function: |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $adsb = WebService::ADSBExchange->new( key => $key, api_url => 'new_api_url.com' ); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 METHODS |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Each method returns the full API response in a hash. The API responds with JSON, and this interface |
|
45
|
|
|
|
|
|
|
parses it into a hash for you to read. A complete example of accessing the information is in the |
|
46
|
|
|
|
|
|
|
synopsis. If you want to mess with the "raw" JSON response, just call get_json_response(). This |
|
47
|
|
|
|
|
|
|
could be useful if you want to inspect the result to determine which pieces of data you want. You |
|
48
|
|
|
|
|
|
|
could also use Data::Dumper on the hash to see everything formatted nice and pretty, but that's |
|
49
|
|
|
|
|
|
|
no fun. |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head2 single_aircraft_position_by_registration |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
$adsb->single_aircraft_position_by_registration('N161UW'); |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head2 single_aircraft_position_by_hex_id |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
$adsb->single_aircraft_position_by_hex_id('A0F73C'); |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 aircraft_live_position_by_hex_id |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
$adsb->aircraft_live_position_by_hex_id('A0F73C'); |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
This call appears to be the same as single_aircraft_position_by_hex_id |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 aircraft_last_position_by_hex_id |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
$adsb->aircraft_last_position_by_hex_id("A0F73C"); |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head2 aircraft_by_callsign |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$adsb->aircraft_by_callsign('AAL2630'); |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head2 aircraft_by_squawk |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
$adsb->aircraft_by_squawk('2025'); |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=head2 tagged_military_aircraft |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$adsb->tagged_military_aircraft(); |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Note this method takes no parameters. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head2 aircraft_within_n_mile_radius |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$adsb->aircraft_within_n_mile_radius( '45.09634', '-94.41019', '30' ); |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Latitude, Longitude, and miles |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head2 do_call |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
do_call is not meant to be accessed directly, but if additional API calls are implemented before this |
|
92
|
|
|
|
|
|
|
interface is updated to use them, you could still use this interface and make the API call like this: |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
$adsb->do_call('new_api_call_example/new_api_call_parameters'); |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
For example, if there was a new API call that returned aircraft by country of registration, it might |
|
97
|
|
|
|
|
|
|
look something like this: |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$adsb->do_call('country/Austria'); |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head2 get_json_response |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
This is the only method that doesn't make an API call; it returns the full JSON response |
|
104
|
|
|
|
|
|
|
from the previous call. This is useful if you wish to see what information is available from the |
|
105
|
|
|
|
|
|
|
call or wish to parse it in a different way. |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
use LWP::UserAgent; |
|
110
|
1
|
|
|
1
|
|
885
|
use HTTP::Request; |
|
|
1
|
|
|
|
|
38862
|
|
|
|
1
|
|
|
|
|
31
|
|
|
111
|
1
|
|
|
1
|
|
7
|
use HTTP::Headers; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
18
|
|
|
112
|
1
|
|
|
1
|
|
4
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
16
|
|
|
113
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
14
|
|
|
114
|
1
|
|
|
1
|
|
4
|
use Moose; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
16
|
|
|
115
|
1
|
|
|
1
|
|
446
|
use Types::Standard qw(Str); |
|
|
1
|
|
|
|
|
343244
|
|
|
|
1
|
|
|
|
|
8
|
|
|
116
|
1
|
|
|
1
|
|
8110
|
use Carp qw(croak); |
|
|
1
|
|
|
|
|
66993
|
|
|
|
1
|
|
|
|
|
26
|
|
|
117
|
1
|
|
|
1
|
|
734
|
use JSON::Parse qw(parse_json); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
48
|
|
|
118
|
1
|
|
|
1
|
|
374
|
|
|
|
1
|
|
|
|
|
1083
|
|
|
|
1
|
|
|
|
|
556
|
|
|
119
|
|
|
|
|
|
|
my $self = shift; |
|
120
|
|
|
|
|
|
|
|
|
121
|
3
|
|
|
3
|
0
|
8339
|
croak |
|
122
|
|
|
|
|
|
|
'You did not specify your API key. <WebService::ADSBExchange->new( key => $key );> To get a key, visit https://rapidapi.com/adsbx/api/adsbexchange-com1' |
|
123
|
3
|
100
|
|
|
|
88
|
if ( !defined $self->key ); |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
return; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
2
|
|
|
|
|
5
|
|
|
128
|
|
|
|
|
|
|
has 'api_url' => ( |
|
129
|
|
|
|
|
|
|
is => 'rw', |
|
130
|
|
|
|
|
|
|
isa => Str, |
|
131
|
|
|
|
|
|
|
default => 'adsbexchange-com1.p.rapidapi.com', |
|
132
|
|
|
|
|
|
|
); |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
has 'key' => ( |
|
135
|
|
|
|
|
|
|
is => 'rw', |
|
136
|
|
|
|
|
|
|
isa => Str |
|
137
|
|
|
|
|
|
|
); |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
has 'json_response' => ( |
|
140
|
|
|
|
|
|
|
is => 'rw', |
|
141
|
|
|
|
|
|
|
isa => Str |
|
142
|
|
|
|
|
|
|
); |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
my ( $self, $callrequest ) = @_; |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
my $full_api_url = 'https://' . $self->api_url; |
|
147
|
1
|
|
|
1
|
1
|
2
|
my $obj_user_agent = LWP::UserAgent->new( timeout => 15 ); |
|
148
|
|
|
|
|
|
|
my $header = HTTP::Headers->new; |
|
149
|
1
|
|
|
|
|
40
|
|
|
150
|
1
|
|
|
|
|
10
|
$header->push_header( 'X-RapidAPI-Key' => $self->key ); |
|
151
|
1
|
|
|
|
|
2313
|
$header->push_header( 'X-RapidAPI-Host' => $self->api_url ); |
|
152
|
|
|
|
|
|
|
my $obj_request = |
|
153
|
1
|
|
|
|
|
35
|
HTTP::Request->new( 'GET', $full_api_url . "/v2/$callrequest/", $header ); |
|
154
|
1
|
|
|
|
|
63
|
my $obj_response = $obj_user_agent->request($obj_request); |
|
155
|
1
|
|
|
|
|
34
|
|
|
156
|
|
|
|
|
|
|
if ( $obj_response->is_error ) { |
|
157
|
1
|
|
|
|
|
6444
|
warn "HTTP request error: " |
|
158
|
|
|
|
|
|
|
. $obj_response->error_as_HTML |
|
159
|
1
|
50
|
|
|
|
1589
|
. " on API Call $callrequest"; |
|
160
|
1
|
|
|
|
|
13
|
|
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
else { |
|
163
|
|
|
|
|
|
|
$self->json_response( $obj_response->content ); |
|
164
|
|
|
|
|
|
|
return parse_json( $obj_response->content ); |
|
165
|
|
|
|
|
|
|
} |
|
166
|
0
|
|
|
|
|
0
|
} |
|
167
|
0
|
|
|
|
|
0
|
|
|
168
|
|
|
|
|
|
|
my $self = shift; |
|
169
|
|
|
|
|
|
|
return $self->json_response; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
173
|
0
|
|
|
|
|
0
|
my $registration = shift; |
|
174
|
|
|
|
|
|
|
return $self->do_call("registration/$registration"); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
178
|
0
|
|
|
|
|
0
|
my $hex_id = shift; |
|
179
|
0
|
|
|
|
|
0
|
return $self->do_call("icao/$hex_id"); |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my $self = shift; |
|
183
|
0
|
|
|
0
|
1
|
0
|
my $hex_id = shift; |
|
184
|
0
|
|
|
|
|
0
|
return $self->do_call("icao/$hex_id"); |
|
185
|
0
|
|
|
|
|
0
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
my $self = shift; |
|
188
|
|
|
|
|
|
|
my $hex_id = shift; |
|
189
|
0
|
|
|
0
|
1
|
0
|
return $self->do_call("hex/$hex_id"); |
|
190
|
0
|
|
|
|
|
0
|
} |
|
191
|
0
|
|
|
|
|
0
|
|
|
192
|
|
|
|
|
|
|
my $self = shift; |
|
193
|
|
|
|
|
|
|
my $callsign = shift; |
|
194
|
|
|
|
|
|
|
return $self->do_call("callsign/$callsign"); |
|
195
|
0
|
|
|
0
|
1
|
0
|
} |
|
196
|
0
|
|
|
|
|
0
|
|
|
197
|
0
|
|
|
|
|
0
|
my $self = shift; |
|
198
|
|
|
|
|
|
|
my $squawk = shift; |
|
199
|
|
|
|
|
|
|
return $self->do_call("sqk/$squawk"); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
1
|
|
|
1
|
1
|
9
|
|
|
202
|
1
|
|
|
|
|
2
|
my $self = shift; |
|
203
|
1
|
|
|
|
|
6
|
return $self->do_call('mil'); |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
my ( $self, $lat, $lon, $dist ) = @_; |
|
207
|
0
|
|
|
0
|
1
|
|
return $self->do_call("lat/$lat/lon/$lon/dist/$dist"); |
|
208
|
0
|
|
|
|
|
|
} |
|
209
|
0
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
1; |