Compare commits
91 Commits
master
...
legacy_dum
| Author | SHA1 | Date |
|---|---|---|
|
|
e993ec1250 | |
|
|
702d7c5423 | |
|
|
e3cd88e24a | |
|
|
5ef9bdd6f3 | |
|
|
727361c1ab | |
|
|
2cf1a40eb6 | |
|
|
161c11d10f | |
|
|
9aa60c46ef | |
|
|
069ebf37c7 | |
|
|
f9c2896404 | |
|
|
9b38353d48 | |
|
|
bbc3412ce2 | |
|
|
9dd09e74ac | |
|
|
5fe52b37b0 | |
|
|
f85b3ead63 | |
|
|
c3000aa020 | |
|
|
3700fa8839 | |
|
|
5ca40d4576 | |
|
|
e64f9abc78 | |
|
|
a7c5eb4b8d | |
|
|
4a477064cf | |
|
|
f199f88283 | |
|
|
69a9b7e47d | |
|
|
97d74b5c53 | |
|
|
603a6e6634 | |
|
|
d8231c2a35 | |
|
|
a9455e143e | |
|
|
a9b662a52c | |
|
|
2ae636846d | |
|
|
bb37c6b4d5 | |
|
|
63dee8bcc6 | |
|
|
750f9b6865 | |
|
|
c1e19917f8 | |
|
|
04a19df6f1 | |
|
|
3120570e1a | |
|
|
8065a22658 | |
|
|
86e11ff509 | |
|
|
87c3c5ae8c | |
|
|
e20e240130 | |
|
|
438d877f98 | |
|
|
3349c172f3 | |
|
|
1a9811d2d5 | |
|
|
bd690db2b3 | |
|
|
c7888add7e | |
|
|
8b4d5b3dca | |
|
|
709889dd5c | |
|
|
e6f2cc5624 | |
|
|
c64a894a18 | |
|
|
a089e07eed | |
|
|
78ee29e334 | |
|
|
1e12168ed6 | |
|
|
2be5074721 | |
|
|
2b92b01194 | |
|
|
fb2f76455c | |
|
|
7d93db06dd | |
|
|
2aea6ec778 | |
|
|
5aab91bbf8 | |
|
|
f486e0ec3a | |
|
|
a8b5a7c85b | |
|
|
1c831ae9a4 | |
|
|
86cd74ae1e | |
|
|
9470ce9304 | |
|
|
0754bb7865 | |
|
|
05e80ee305 | |
|
|
f911346f87 | |
|
|
a4c586a8a1 | |
|
|
013133e1eb | |
|
|
298afdaa8f | |
|
|
84fa09c228 | |
|
|
f44130ba33 | |
|
|
d848a94358 | |
|
|
3e3c525b0b | |
|
|
db2f7d6a0e | |
|
|
13ce9dd453 | |
|
|
0880eedee7 | |
|
|
2ede6fb51f | |
|
|
0317c48aac | |
|
|
21d08814ca | |
|
|
e38d778ec5 | |
|
|
5a2bf79cfe | |
|
|
9b619927ae | |
|
|
5d8df9c7e4 | |
|
|
2cdb8fa612 | |
|
|
b20bac223a | |
|
|
fde30c96b7 | |
|
|
3d9bc4f798 | |
|
|
8c9bd4f5c3 | |
|
|
d3012b516c | |
|
|
addb94b1bb | |
|
|
ed17d9629e | |
|
|
807c1aba7f |
|
|
@ -1,5 +1,7 @@
|
||||||
*.o
|
*.o
|
||||||
dump1090
|
dump1090
|
||||||
|
faup1090
|
||||||
|
view1090
|
||||||
testfiles/*.bin
|
testfiles/*.bin
|
||||||
misc
|
misc
|
||||||
frames.js
|
frames.js
|
||||||
|
|
|
||||||
20
Makefile
20
Makefile
|
|
@ -4,14 +4,20 @@
|
||||||
#
|
#
|
||||||
PROGNAME=dump1090
|
PROGNAME=dump1090
|
||||||
|
|
||||||
|
include /usr/share/dpkg/buildflags.mk
|
||||||
|
|
||||||
|
PREFIX=/usr
|
||||||
|
|
||||||
ifdef PREFIX
|
ifdef PREFIX
|
||||||
BINDIR=$(PREFIX)/bin
|
BINDIR=$(PREFIX)/bin
|
||||||
SHAREDIR=$(PREFIX)/share/$(PROGNAME)
|
SHAREDIR=$(PREFIX)/share/$(PROGNAME)
|
||||||
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
HTMLDIR=$(SHAREDIR)/public_html
|
||||||
|
EXTRACFLAGS=-DHTMLPATH=\"$(HTMLDIR)\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
#CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
||||||
LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
|
CFLAGS+=$(shell pkg-config --cflags librtlsdr)
|
||||||
|
LIBS=-Wl,-Bstatic -lrtlsdr -Wl,-Bdynamic -lusb-1.0 -lpthread -lm
|
||||||
CC=gcc
|
CC=gcc
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -28,3 +34,11 @@ view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o dump1090 view1090
|
rm -f *.o dump1090 view1090
|
||||||
|
|
||||||
|
install-doc:
|
||||||
|
$(MAKE) -C doc install
|
||||||
|
|
||||||
|
install: install-doc
|
||||||
|
install -t $(BINDIR) dump1090 view1090
|
||||||
|
mkdir -p $(HTMLDIR)
|
||||||
|
cp -R public_html $(SHAREDIR)
|
||||||
|
|
|
||||||
425
README.md
425
README.md
|
|
@ -1,284 +1,147 @@
|
||||||
Dump1090 README
|
## Dump1090 MR README
|
||||||
===
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
Dump1090 MR is a FlightAware fork of Malcolm Robb's fork of
|
||||||
|
Salvatore Sanfilippo's dump1090 program. FlightAware uses it as an
|
||||||
|
important element of PiAware (https://flightaware.com/adsb/piaware/),
|
||||||
|
a Debian package for forwarding ADS-B data to FlightAware.
|
||||||
|
|
||||||
|
Salvatore also invented an extremely popular in-memory database called redis,
|
||||||
|
among other things, and he's pretty busy and doesn't have a lot of time to
|
||||||
|
jack with dump1090.
|
||||||
|
|
||||||
|
Malcolm split out dump1090's source code out into several different files
|
||||||
|
and has done steady work maintaining and updgrading it. People have been
|
||||||
|
sending him patches in the form of pull requests and he's been assiduously
|
||||||
|
bringing them into the mainline code.
|
||||||
|
|
||||||
|
Although dump1090 is presented primarily as an ADS-B (Mode S) decoder
|
||||||
|
specifically designed for these little RTLSDR USB dongles that contain
|
||||||
|
a software defined radio and FPGA and were originally intended for decoding
|
||||||
|
certain satellite TV broadcasts, dump1090 can do many other useful things
|
||||||
|
such as
|
||||||
|
* decode and interpret ADS-B messages from various formats
|
||||||
|
* Stream ADS-B messages in various formats using Internet-standard TCP sockets
|
||||||
|
* provide a web interface to show aircraft traffic on a map in real time
|
||||||
|
* and more
|
||||||
|
|
||||||
|
Since airborne aircraft transmit their positions twice each second, ADS-B
|
||||||
|
receivers located in high traffic areas can receive as many as thousands
|
||||||
|
of messages each second.
|
||||||
|
|
||||||
|
Much of this information can be filtered out without a significant loss
|
||||||
|
of fidelity at the receiving end. For example, an aircraft flying at
|
||||||
|
a high altitude with a consistent heading and speed, the aircraft's
|
||||||
|
location information can be forwarded less frequently.
|
||||||
|
|
||||||
|
Also aircraft equipped with legacy transponders, as most still are, only
|
||||||
|
their altitude is being transmitted, not their latitude and longitude, etc,
|
||||||
|
and as these messages aren't as useful they don't need to be sent as often.
|
||||||
|
|
||||||
|
The FlightAware fork leverages dump1090 to create a new message format
|
||||||
|
that is filtered as described above plus with additional criteria
|
||||||
|
and then we group multiple messages together into a single TCP packet
|
||||||
|
to reduce overhead (as each IPv4 packet has a 64-byte header),
|
||||||
|
ultimately requiring a small fraction of the bandwidth used by the other
|
||||||
|
data formats dump1090 can send natively. This is on port 10001 by default.
|
||||||
|
|
||||||
|
Within the dump1090 repo also is a program called faup1090. When someone
|
||||||
|
is running their own dump1090 or native Malcolm Robb dump1090, faup1090
|
||||||
|
can connect to dump1090, interpret the packets it receives, and translate
|
||||||
|
them into the same filtered format our fork of dump1090 produces.
|
||||||
|
|
||||||
|
FlightAware's PiAware Debian package (https://flightaware.com/adsb/piaware/) leverages either faup1090 or dump1090
|
||||||
|
with additional software to connect to FlightAware with a compressed,
|
||||||
|
encrypted TLS connection, log in using your FlightAware account and
|
||||||
|
password, and forward your ADS-B data, where it is collected as part of
|
||||||
|
FlightAware's worldwide network of Airspace National Service Providers,
|
||||||
|
satellite tracking providers, networks of ADS-B providers, our FA-managed
|
||||||
|
ADS-B network.
|
||||||
|
|
||||||
|
By contributing your ADS-B data to FlightAware you
|
||||||
|
* contribute to the accuracy of FlightAware's flight tracking, almost all of which is available for free worldwide through the FA website in 15 languages
|
||||||
|
* gain the ability to see a realtime picture of all ADS-B traffic FlightAware knows about
|
||||||
|
* make the Internet itself more useful
|
||||||
|
* help people communicate and share information
|
||||||
|
|
||||||
|
Every day hundreds of thousands of people save time and energy using
|
||||||
|
FlightAware. If someone leaves for the airport an hour later because the
|
||||||
|
flight they're meeting is an hour late, they got an hour of their life
|
||||||
|
back, and that's an hour not spent in their car with the engine running
|
||||||
|
or whatever. It's a win for the person, a win for the environment, and
|
||||||
|
your contribution to that is palpable.
|
||||||
|
|
||||||
|
While doing this, FlightAware in no way restricts your ability to share your
|
||||||
|
ADS-B data with other flight trackers.
|
||||||
|
|
||||||
|
Most people will have no need to grab dump1090/faup1090 from source code and
|
||||||
|
build it. If you already have dump1090 running with some sort of ADS-B
|
||||||
|
receiver, all you need to send stuff to FlightAware is to install our
|
||||||
|
Debian package and configure it with your user name and password.
|
||||||
|
|
||||||
|
But for the intrepid, here is the source code, in all its glory, freely
|
||||||
|
redistributable under the permissive Berkeley copyright, modifiable for
|
||||||
|
your use and others, including for profit, should you desire.
|
||||||
|
|
||||||
|
We will continue to track the Malcolm Robb fork of dump1090 for the
|
||||||
|
foreseeable future and maintain our modifications. We solicit any bug
|
||||||
|
reports and bug fixes are, as always, for the same.
|
||||||
|
|
||||||
|
PiAware source code and instructions on build it can be found at
|
||||||
|
https://github.com/flightaware/piaware.
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
#### build and install RTL-SDR libraries
|
||||||
|
|
||||||
|
Below is a pretty standard recipe for building and installing the libraries to talk to the RTL-SDR software defined radio USB dongle.
|
||||||
|
|
||||||
|
Following this recipe builds these with a prefix of /usr instead of the default /usr/local, because Linux. These paths are also used for (and RTL-SDR files included in) the FlightAware-sourced dump1090 install package.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev
|
||||||
|
git clone git://git.osmocom.org/rtl-sdr.git
|
||||||
|
cd rtl-sdr
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr ..
|
||||||
|
make all
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
#### build and install dump1090
|
||||||
|
|
||||||
|
To build dump1090...
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
To build and install faup1090 only...
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
make -f makefaup1090 all
|
||||||
|
sudo make -f makefaup1090 install-faup1090
|
||||||
|
```
|
||||||
|
|
||||||
|
To build and install both faup1090 and dump1090...
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
make -f makefaup1090 all
|
||||||
|
sudo make -f makefaup1090 install-faup1090 install-dump1090
|
||||||
|
```
|
||||||
|
|
||||||
|
To build and install dump1090 and faup1090 and configure the system to start them automatically whenever the system boots
|
||||||
|
|
||||||
Dump 1090 is a Mode S decoder specifically designed for RTLSDR devices.
|
```
|
||||||
|
make
|
||||||
|
make -f makefaup1090 all
|
||||||
|
sudo make -f makefaup1090 full-install
|
||||||
|
```
|
||||||
|
|
||||||
|
### For more information
|
||||||
|
Please read the original README and the Malcolm Robb ones at https://github.com/antirez/dump1090 and https://github.com/malcolmrobb/dump1090, respectively.
|
||||||
|
|
||||||
The main features are:
|
|
||||||
|
|
||||||
* Robust decoding of weak messages, with mode1090 many users observed
|
|
||||||
improved range compared to other popular decoders.
|
|
||||||
* Network support: TCP30003 stream (MSG5...), Raw packets, HTTP.
|
|
||||||
* Embedded HTTP server that displays the currently detected aircrafts on
|
|
||||||
Google Map.
|
|
||||||
* Single bit errors correction using the 24 bit CRC.
|
|
||||||
* Ability to decode DF11, DF17 messages.
|
|
||||||
* Ability to decode DF formats like DF0, DF4, DF5, DF16, DF20 and DF21
|
|
||||||
where the checksum is xored with the ICAO address by brute forcing the
|
|
||||||
checksum field using recently seen ICAO addresses.
|
|
||||||
* Decode raw IQ samples from file (using --ifile command line switch).
|
|
||||||
* Interactive command-line-interfae mode where aircrafts currently detected
|
|
||||||
are shown as a list refreshing as more data arrives.
|
|
||||||
* CPR coordinates decoding and track calculation from velocity.
|
|
||||||
* TCP server streaming and recceiving raw data to/from connected clients
|
|
||||||
(using --net).
|
|
||||||
|
|
||||||
Installation
|
|
||||||
---
|
|
||||||
|
|
||||||
Type "make".
|
|
||||||
|
|
||||||
Normal usage
|
|
||||||
---
|
|
||||||
|
|
||||||
To capture traffic directly from your RTL device and show the captured traffic
|
|
||||||
on standard output, just run the program without options at all:
|
|
||||||
|
|
||||||
./dump1090
|
|
||||||
|
|
||||||
To just output hexadecimal messages:
|
|
||||||
|
|
||||||
./dump1090 --raw
|
|
||||||
|
|
||||||
To run the program in interactive mode:
|
|
||||||
|
|
||||||
./dump1090 --interactive
|
|
||||||
|
|
||||||
To run the program in interactive mode, with networking support, and connect
|
|
||||||
with your browser to http://localhost:8080 to see live traffic:
|
|
||||||
|
|
||||||
./dump1090 --interactive --net
|
|
||||||
|
|
||||||
In iteractive mode it is possible to have a less information dense but more
|
|
||||||
"arcade style" output, where the screen is refreshed every second displaying
|
|
||||||
all the recently seen aircrafts with some additional information such as
|
|
||||||
altitude and flight number, extracted from the received Mode S packets.
|
|
||||||
|
|
||||||
Using files as source of data
|
|
||||||
---
|
|
||||||
|
|
||||||
To decode data from file, use:
|
|
||||||
|
|
||||||
./dump1090 --ifile /path/to/binfile
|
|
||||||
|
|
||||||
The binary file should be created using `rtl_sdr` like this (or with any other
|
|
||||||
program that is able to output 8-bit unsigned IQ samples at 2Mhz sample rate).
|
|
||||||
|
|
||||||
rtl_sdr -f 1090000000 -s 2000000 -g 50 output.bin
|
|
||||||
|
|
||||||
In the example `rtl_sdr` a gain of 50 is used, simply you should use the highest
|
|
||||||
gain availabe for your tuner. This is not needed when calling Dump1090 itself
|
|
||||||
as it is able to select the highest gain supported automatically.
|
|
||||||
|
|
||||||
It is possible to feed the program with data via standard input using
|
|
||||||
the --ifile option with "-" as argument.
|
|
||||||
|
|
||||||
Additional options
|
|
||||||
---
|
|
||||||
|
|
||||||
Dump1090 can be called with other command line options to set a different
|
|
||||||
gain, frequency, and so forth. For a list of options use:
|
|
||||||
|
|
||||||
./dump1090 --help
|
|
||||||
|
|
||||||
Everything is not documented here should be obvious, and for most users calling
|
|
||||||
it without arguments at all is the best thing to do.
|
|
||||||
|
|
||||||
Reliability
|
|
||||||
---
|
|
||||||
|
|
||||||
By default Dump1090 checks for decoding errors using the 24-bit CRC checksum,
|
|
||||||
where available. Messages with errors are discarded.
|
|
||||||
|
|
||||||
The --fix command line switch enables fixing single bit error correction
|
|
||||||
based on the CRC checksum. Technically, it uses a table of precomputed
|
|
||||||
checksum differences resulting from single bit errors to look up the
|
|
||||||
wrong bit position.
|
|
||||||
|
|
||||||
This is indeed able to fix errors and works reliably in my experience,
|
|
||||||
however if you are interested in very reliable data I suggest to use
|
|
||||||
the --no-fix command line switch in order to disable error fixing.
|
|
||||||
|
|
||||||
Performances and sensibility of detection
|
|
||||||
---
|
|
||||||
|
|
||||||
In my limited experience Dump1090 was able to decode a big number of messages
|
|
||||||
even in conditions where I encountered problems using other programs, however
|
|
||||||
no formal test was performed so I can't really claim that this program is
|
|
||||||
better or worse compared to other similar programs.
|
|
||||||
|
|
||||||
If you can capture traffic that Dump1090 is not able to decode properly, drop
|
|
||||||
me an email with a download link. I may try to improve the detection during
|
|
||||||
my free time (this is just an hobby project).
|
|
||||||
|
|
||||||
Network server features
|
|
||||||
---
|
|
||||||
|
|
||||||
By enabling the networking support with --net Dump1090 starts listening
|
|
||||||
for clients connections on port 30002 and 30001 (you can change both the
|
|
||||||
ports if you want, see --help output).
|
|
||||||
|
|
||||||
Port 30002
|
|
||||||
---
|
|
||||||
|
|
||||||
Connected clients are served with data ASAP as they arrive from the device
|
|
||||||
(or from file if --ifile is used) in the raw format similar to the following:
|
|
||||||
|
|
||||||
*8D451E8B99019699C00B0A81F36E;
|
|
||||||
|
|
||||||
Every entry is separated by a simple newline (LF character, hex 0x0A).
|
|
||||||
|
|
||||||
Port 30001
|
|
||||||
---
|
|
||||||
|
|
||||||
Port 30001 is the raw input port, and can be used to feed Dump1090 with
|
|
||||||
data in the same format as specified above, with hex messages starting with
|
|
||||||
a `*` and ending with a `;` character.
|
|
||||||
|
|
||||||
So for instance if there is another remote Dump1090 instance collecting data
|
|
||||||
it is possible to sum the output to a local Dump1090 instance doing something
|
|
||||||
like this:
|
|
||||||
|
|
||||||
nc remote-dump1090.example.net 30002 | nc localhost 30001
|
|
||||||
|
|
||||||
It is important to note that what is received via port 30001 is also
|
|
||||||
broadcasted to clients listening to port 30002.
|
|
||||||
|
|
||||||
In general everything received from port 30001 is handled exactly like the
|
|
||||||
normal traffic from RTL devices or from file when --ifile is used.
|
|
||||||
|
|
||||||
It is possible to use Dump1090 just as an hub using --ifile with /dev/zero
|
|
||||||
as argument as in the following example:
|
|
||||||
|
|
||||||
./dump1090 --net-only
|
|
||||||
|
|
||||||
Or alternatively to see what's happening on the screen:
|
|
||||||
|
|
||||||
./dump1090 --net-only --interactive
|
|
||||||
|
|
||||||
Then you can feed it from different data sources from the internet.
|
|
||||||
|
|
||||||
Port 30003
|
|
||||||
---
|
|
||||||
|
|
||||||
Connected clients are served with messages in SBS1 (BaseStation) format,
|
|
||||||
similar to:
|
|
||||||
|
|
||||||
MSG,4,,,738065,,,,,,,,420,179,,,0,,0,0,0,0
|
|
||||||
MSG,3,,,738065,,,,,,,35000,,,34.81609,34.07810,,,0,0,0,0
|
|
||||||
|
|
||||||
This can be used to feed data to various sharing sites without the need to use another decoder.
|
|
||||||
|
|
||||||
Antenna
|
|
||||||
---
|
|
||||||
|
|
||||||
Mode S messages are transmitted in the 1090 Mhz frequency. If you have a decent
|
|
||||||
antenna you'll be able to pick up signals from aircrafts pretty far from your
|
|
||||||
position, especially if you are outdoor and in a position with a good sky view.
|
|
||||||
|
|
||||||
You can easily build a very cheap antenna following the istructions at:
|
|
||||||
|
|
||||||
http://antirez.com/news/46
|
|
||||||
|
|
||||||
With this trivial antenna I was able to pick up signals of aircrafts 200+ Km
|
|
||||||
away from me.
|
|
||||||
|
|
||||||
If you are interested in a more serious antenna check the following
|
|
||||||
resources:
|
|
||||||
|
|
||||||
* http://gnuradio.org/redmine/attachments/download/246/06-foster-adsb.pdf
|
|
||||||
* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html
|
|
||||||
* http://modesbeast.com/pix/adsb-ant-drawing.gif
|
|
||||||
|
|
||||||
Aggressive mode
|
|
||||||
---
|
|
||||||
|
|
||||||
With --aggressive it is possible to activate the *aggressive mode* that is a
|
|
||||||
modified version of the Mode S packet detection and decoding.
|
|
||||||
The aggresive mode uses more CPU usually (especially if there are many planes
|
|
||||||
sending DF17 packets), but can detect a few more messages.
|
|
||||||
|
|
||||||
The algorithm in aggressive mode is modified in the following ways:
|
|
||||||
|
|
||||||
* Up to two demodulation errors are tolerated (adjacent entires in the
|
|
||||||
magnitude vector with the same eight). Normally only messages without
|
|
||||||
errors are checked.
|
|
||||||
* It tries to fix DF17 messages with CRC errors resulting from any two bit
|
|
||||||
errors.
|
|
||||||
|
|
||||||
The use of aggressive mdoe is only advised in places where there is
|
|
||||||
low traffic in order to have a chance to capture some more messages.
|
|
||||||
|
|
||||||
Debug mode
|
|
||||||
---
|
|
||||||
|
|
||||||
The Debug mode is a visual help to improve the detection algorithm or to
|
|
||||||
understand why the program is not working for a given input.
|
|
||||||
|
|
||||||
In this mode messages are displayed in an ASCII-art style graphical
|
|
||||||
representation, where the individial magnitude bars sampled at 2Mhz are
|
|
||||||
displayed.
|
|
||||||
|
|
||||||
An index shows the sample number, where 0 is the sample where the first
|
|
||||||
Mode S peak was found. Some additional background noise is also added
|
|
||||||
before the first peak to provide some context.
|
|
||||||
|
|
||||||
To enable debug mode and check what combinations of packets you can
|
|
||||||
log, use `mode1090 --help` to obtain a list of available debug flags.
|
|
||||||
|
|
||||||
Debug mode includes an optional javascript output that is used to visualize
|
|
||||||
packets using a web browser, you can use the file debug.html under the
|
|
||||||
'tools' directory to load the generated frames.js file.
|
|
||||||
|
|
||||||
How this program works?
|
|
||||||
---
|
|
||||||
|
|
||||||
The code is very documented and written in order to be easy to understand.
|
|
||||||
For the diligent programmer with a Mode S specification on his hands it
|
|
||||||
should be trivial to understand how it works.
|
|
||||||
|
|
||||||
The algorithms I used were obtained basically looking at many messages
|
|
||||||
as displayed using a trow-away SDL program, and trying to model the algorithm
|
|
||||||
based on how the messages look graphically.
|
|
||||||
|
|
||||||
How to test the program?
|
|
||||||
---
|
|
||||||
|
|
||||||
If you have an RTLSDR device and you happen to be in an area where there
|
|
||||||
are aircrafts flying over your head, just run the program and check for signals.
|
|
||||||
|
|
||||||
However if you don't have an RTLSDR device, or if in your area the presence
|
|
||||||
of aircrafts is very limited, you may want to try the sample file distributed
|
|
||||||
with the Dump1090 distribution under the "testfiles" directory.
|
|
||||||
|
|
||||||
Just run it like this:
|
|
||||||
|
|
||||||
./dump1090 --ifile testfiles/modes1.bin
|
|
||||||
|
|
||||||
What is --strip mode?
|
|
||||||
---
|
|
||||||
|
|
||||||
It is just a simple filter that will get raw IQ 8 bit samples in input
|
|
||||||
and will output a file missing all the parts of the file where I and Q
|
|
||||||
are lower than the specified <level> for more than 32 samples.
|
|
||||||
|
|
||||||
Use it like this:
|
|
||||||
|
|
||||||
cat big.bin | ./dump1090 --snip 25 > small.bin
|
|
||||||
|
|
||||||
I used it in order to create a small test file to include inside this
|
|
||||||
program source code distribution.
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
---
|
|
||||||
|
|
||||||
Dump1090 was written during some free time during xmas 2012, it is an hobby
|
|
||||||
project so I'll be able to address issues and improve it only during
|
|
||||||
free time, however you are incouraged to send pull requests in order to
|
|
||||||
improve the program. A good starting point can be the TODO list included in
|
|
||||||
the source distribution.
|
|
||||||
|
|
||||||
Credits
|
|
||||||
---
|
|
||||||
|
|
||||||
Dump1090 was written by Salvatore Sanfilippo <antirez@gmail.com> and is
|
|
||||||
released under the BSD three clause license.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# link command
|
||||||
|
# we don't need -lusb-1.0
|
||||||
|
gcc -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o -L/usr/local/lib -lrtlsdr -lcompat -lpthread -lm
|
||||||
2
anet.c
2
anet.c
|
|
@ -343,3 +343,5 @@ int anetSockName(int fd, char *ip, int *port) {
|
||||||
if (port) *port = ntohs(sa.sin_port);
|
if (port) *port = ntohs(sa.sin_port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
2
anet.h
2
anet.h
|
|
@ -57,3 +57,5 @@ int anetPeerToString(int fd, char *ip, int *port);
|
||||||
int anetSetSendBuffer(char *err, int fd, int buffsize);
|
int anetSetSendBuffer(char *err, int fd, int buffsize);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# makefile for piaware doc files
|
||||||
|
#
|
||||||
|
|
||||||
|
DOCDIR=/usr/share/man/man1
|
||||||
|
|
||||||
|
MANPAGES= dump1090.1
|
||||||
|
|
||||||
|
all:
|
||||||
|
@echo "'make install' to install docs"
|
||||||
|
|
||||||
|
install:
|
||||||
|
@echo ---- installing docs
|
||||||
|
cp $(MANPAGES) $(DOCDIR)
|
||||||
|
@echo --- compressing docs
|
||||||
|
cd $(DOCDIR); gzip --force -9 $(MANPAGES)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2014 FlightAware LLC
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Dd October 19, 2014
|
||||||
|
.Dt DUMP1090 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm dump1090
|
||||||
|
.Nd decode, translate and communicate Mode S (ADS-B) aviation messages
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm dump1090
|
||||||
|
.Bk -words
|
||||||
|
.Op Fl -device-index Ar index
|
||||||
|
.Op Fl -gain Ar db
|
||||||
|
.Op Fl -enable-agc
|
||||||
|
.Op Fl -freq Ar hz
|
||||||
|
.Op Fl -interactive
|
||||||
|
.Op Fl -interactive-rows Ar num
|
||||||
|
.Op Fl -interactive-ttl Ar sec
|
||||||
|
.Op Fl -interactive-rtl1090
|
||||||
|
.Op Fl -raw
|
||||||
|
.Op Fl -net
|
||||||
|
.Op Fl -modeac
|
||||||
|
.Op Fl -net-beast
|
||||||
|
.Op Fl -net-only
|
||||||
|
.Op Fl -no-rtlsdr-ok
|
||||||
|
.Op Fl -net-fatsv-port Ar port
|
||||||
|
.Op Fl -net-ri-port Ar port
|
||||||
|
.Op Fl -net-ro-port Ar port
|
||||||
|
.Op Fl -net-sbs-port Ar port
|
||||||
|
.Op Fl -net-bi-port Ar port
|
||||||
|
.Op Fl -net-bo-port Ar port
|
||||||
|
.Op Fl -net-ro-size Ar size
|
||||||
|
.Op Fl -net-ro-rate Ar rate
|
||||||
|
.Op Fl -net-heartbeat Ar rate
|
||||||
|
.Op Fl -net-buffer Ar n
|
||||||
|
.Op Fl -lat Ar latitude
|
||||||
|
.Op Fl -lon Ar longitude
|
||||||
|
.Op Fl -fix
|
||||||
|
.Op Fl -no-fix
|
||||||
|
.Op Fl -no-crc-check
|
||||||
|
.Op Fl -phase-enhance
|
||||||
|
.Op Fl -aggressive
|
||||||
|
.Op Fl -mlat
|
||||||
|
.Op Fl -stats
|
||||||
|
.Op Fl -stats-every Ar seconds
|
||||||
|
.Op Fl -onlyaddr
|
||||||
|
.Op Fl -metric
|
||||||
|
.Op Fl -snip Ar level
|
||||||
|
.Op Fl -debug Ar flags
|
||||||
|
.Op Fl -quiet
|
||||||
|
.Op Fl -ppm Ar error
|
||||||
|
.Op Fl -help
|
||||||
|
.Ek
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
Dump1090 receives Mode S (ADS-B) messages from RTL-SDR (Software Defined
|
||||||
|
Radio) USB dongles and optionally network sources and makes those messages
|
||||||
|
available in various formats as a server on various TCP ports.
|
||||||
|
|
||||||
|
It also includes a mini-webserver that provides a moving map display of
|
||||||
|
nearby detected aircraft to web browsers on the LAN.
|
||||||
|
.Pp
|
||||||
|
.Nm
|
||||||
|
established an encrypted, compressed TLS connection with FligthAware and logs
|
||||||
|
in using a FlightAware user name and password.
|
||||||
|
At the same time it tries to
|
||||||
|
connect to a program on the local computer providing ADS-B messages in
|
||||||
|
"beast" binary format, typically \fBdump1090\fR.
|
||||||
|
.Pp
|
||||||
|
It then filters and coalesces those messages and forwards them over the
|
||||||
|
TLS connection where they contribute to the accuracy of FlightAware's
|
||||||
|
flight tracking.
|
||||||
|
.Pp
|
||||||
|
(People who forward ADS-B messages to FlightAware automatically qualify for
|
||||||
|
a free upgrade to an Enterprise Account. For more information please visit
|
||||||
|
http://flightaware.com/adsb/piaware/)
|
||||||
|
.Pp
|
||||||
|
On startup piaware attempts to connect to port 10001 to obtain the filtered,
|
||||||
|
coalesced ADS-B messages. If the machine is running the FlightAware-modified
|
||||||
|
version of dump1090 (https://github.com/flightaware/dump1090_mr) then it
|
||||||
|
will obtain those messages directly.
|
||||||
|
.Pp
|
||||||
|
If the site is not running FA-modified dump1090 or is running a different
|
||||||
|
ADS-B provider program such as modesmixer then piaware will start a helper
|
||||||
|
program called faup1090 to translate between beast format and FlightAware
|
||||||
|
format.
|
||||||
|
.Pp
|
||||||
|
If installed from the Debian package, piaware will automatically start up at system boot time.
|
||||||
|
.Pp
|
||||||
|
Since other programs such as dump1090 may not have started yet, piaware will wait until something is there to provide ADS-B data. Also piaware will automatically reconnect if that program stops and is started again and it will also periodically try to reconnect to FlightAware in the event that contact is lost.
|
||||||
|
.Pp
|
||||||
|
Options:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl -device-index Ar index
|
||||||
|
Select which RTL device to use if multiple are present. The default is 0.
|
||||||
|
.It Fl -gain Ar db
|
||||||
|
Sets the gain of the RTL-SDR device. The default is to set for max gain. Use -10 for auto-gain.
|
||||||
|
.It Fl -enable-agc
|
||||||
|
Enable RTL-SDR automatic gain control. AGC default state is off.
|
||||||
|
.It Fl -freq Ar hz
|
||||||
|
Sets the frequency sampled by the RTL-SDR device. The default os 1090 MHz.
|
||||||
|
.It Fl -interactive
|
||||||
|
ENable interactive mode, periodically refreshing data on the terminal screen.
|
||||||
|
.It Fl -interactive-rows Ar num
|
||||||
|
Specifes the maximum number of rows presented in interactive mode. The default is 15.
|
||||||
|
.It Fl -interactive-ttl Ar sec
|
||||||
|
Sets the number of seconds before aircraft are removed from the interactive display when no new messages have been received from that aircraft. The default is 60 seconds.
|
||||||
|
.It Fl -interactive-rtl1090
|
||||||
|
Display the flight table in RTL1090 format.
|
||||||
|
.It Fl -raw
|
||||||
|
Show only messages' hex values.
|
||||||
|
.It Fl -net
|
||||||
|
Enable networking.
|
||||||
|
.It Fl -modeac
|
||||||
|
Enable decoding of SSR Mode-S 3/A and 3/C messages.
|
||||||
|
.It Fl -net-beast
|
||||||
|
Produce TCP raw output in Beast binary format
|
||||||
|
.It Fl -net-only
|
||||||
|
Enable just networking, don't even look for an RTL-SDR device.
|
||||||
|
.It Fl -no-rtlsdr-ok
|
||||||
|
Probe for an RTL-SDR device but keep going if one isn't found. By default
|
||||||
|
dump1090 will exit if there is no RTL-SDR device found but this switch used
|
||||||
|
with the --net switch allows
|
||||||
|
.Nm
|
||||||
|
to start up as an ADS-B internetworked format translation service whether there is a local RTL device or not.
|
||||||
|
.It Fl -net-fatsv-port Ar port
|
||||||
|
Specify the FlightAware TSV-style output port. The default is 10001.
|
||||||
|
.It Fl -net-ri-port Ar port
|
||||||
|
Specify the TCP raw input listening port. The default is 30001. This port can be connected to by data senders to push raw ADS-B messages to.
|
||||||
|
.It Fl -net-ro-port Ar port
|
||||||
|
Specify the raw output listening port. The default is 30002. Processes that connect to this port will receive messages received by dump1090 either from the radio source or a network source, in raw format.
|
||||||
|
.It Fl -net-sbs-port Ar port
|
||||||
|
Processes that connect to this port (default 30003) will receive ADS-B messages in Kinetic SBS format.
|
||||||
|
.It Fl -net-bi-port Ar port
|
||||||
|
Processes that connect to this port (default 30004) can send ADS-B messages to
|
||||||
|
.Nm
|
||||||
|
in Mode S Beast format.
|
||||||
|
.It Fl -net-bo-port Ar port
|
||||||
|
Processes that connect to this port (default 30005) will receive ADS-B messages from dump1090 in Mode S Besat format.
|
||||||
|
.It Fl -net-ro-size Ar size
|
||||||
|
Raw output minimum size. Not sure.
|
||||||
|
.It Fl -net-ro-rate Ar rate
|
||||||
|
Raw memory flush rate. Not sure.
|
||||||
|
.It Fl -net-heartbeat Ar rate
|
||||||
|
TCP heartbeat rate in seconds. The default is 60 seconds. Set to 0 to disable.
|
||||||
|
.It Fl -net-buffer Ar n
|
||||||
|
Specify the TCP buffer size as N where the amount is 64 KByte * 2^N. The default is 0, 64 KBytes.
|
||||||
|
.It Fl -lat Ar latitude
|
||||||
|
Specify the receiver latitude. If specified provides reference information for surface position messages.
|
||||||
|
.It Fl -lon Ar longitude
|
||||||
|
Specify the receiver longitude. If specified provides reference information for surface position messages.
|
||||||
|
.It Fl -fix
|
||||||
|
Enable single-bit error correction using CRC.
|
||||||
|
.It Fl -no-fix
|
||||||
|
Disable single-bit error correction using CRC.
|
||||||
|
.It Fl -no-crc-check
|
||||||
|
Still process messages with broken CRC. (strongly discouraged)
|
||||||
|
.It Fl -phase-enhance
|
||||||
|
Enable phase enhancement during RTL-SDR decoding.
|
||||||
|
.It Fl -aggressive
|
||||||
|
Aggressively attempt to use more CPU power to decode more messages. Not recommended by Malcolm Robb and/or FlightAware if you are sharing due to its propensity to produce incorrect messages.
|
||||||
|
.It Fl -mlat
|
||||||
|
Not sure.
|
||||||
|
.It Fl -stats
|
||||||
|
With --ifile print stats at exit. Produces no other output. Only useful for testing and experimenting with dump1090 itself.
|
||||||
|
.It Fl -stats-every Ar seconds
|
||||||
|
Show and restat stats every this-many seconds.
|
||||||
|
.It Fl -onlyaddr
|
||||||
|
Show only ICAO addresses. Useful only for testing purposes.
|
||||||
|
.It Fl -metric
|
||||||
|
Use metric units (meters, KM/h, etc) rather than standard aviation units.
|
||||||
|
.It Fl -snip Ar level
|
||||||
|
Strip IQ file, removing samples that are less than the value of the specified level. Again only useful for testing dump1090.
|
||||||
|
.It Fl -debug Ar flags
|
||||||
|
Enable verbose debugging modes, see the README file for details.
|
||||||
|
.It Fl -quiet
|
||||||
|
Disable output to standard out. Use for applications where dump1090 is run as a daemon.
|
||||||
|
.It Fl -ppm Ar error
|
||||||
|
Set the receiver error rate in parts per million. The default is 0.
|
||||||
|
.It Fl -help
|
||||||
|
Emit a brief summary of
|
||||||
|
.Nm
|
||||||
|
usage options.
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
Run dump1090 from the command line in quiet mode, with network support,
|
||||||
|
with it being OK if there is no RTL-SDR dongle attached, and with some
|
||||||
|
network buffering and rate switches:
|
||||||
|
.Pp
|
||||||
|
.Dl $ dump1090 --quiet --no-rtlsdr-ok --net --net-ro-size 500 --net-ro-rate 5 --net-buffer 5
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr faup1090
|
||||||
28
dump1090.c
28
dump1090.c
|
|
@ -29,6 +29,7 @@
|
||||||
//
|
//
|
||||||
#include "coaa.h"
|
#include "coaa.h"
|
||||||
#include "dump1090.h"
|
#include "dump1090.h"
|
||||||
|
#include "rtl-sdr.h"
|
||||||
//
|
//
|
||||||
// ============================= Utility functions ==========================
|
// ============================= Utility functions ==========================
|
||||||
//
|
//
|
||||||
|
|
@ -77,6 +78,8 @@ void modesInitConfig(void) {
|
||||||
Modes.net_output_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
|
Modes.net_output_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
|
||||||
Modes.net_input_beast_port = MODES_NET_INPUT_BEAST_PORT;
|
Modes.net_input_beast_port = MODES_NET_INPUT_BEAST_PORT;
|
||||||
Modes.net_http_port = MODES_NET_HTTP_PORT;
|
Modes.net_http_port = MODES_NET_HTTP_PORT;
|
||||||
|
Modes.net_fatsv_port = MODES_NET_OUTPUT_FA_TSV_PORT;
|
||||||
|
Modes.no_rtlsdr_ok = 0;
|
||||||
Modes.interactive_rows = getTermRows();
|
Modes.interactive_rows = getTermRows();
|
||||||
Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL;
|
Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL;
|
||||||
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
|
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
|
||||||
|
|
@ -191,7 +194,7 @@ void modesInit(void) {
|
||||||
//
|
//
|
||||||
// =============================== RTLSDR handling ==========================
|
// =============================== RTLSDR handling ==========================
|
||||||
//
|
//
|
||||||
void modesInitRTLSDR(void) {
|
int modesInitRTLSDR(void) {
|
||||||
int j;
|
int j;
|
||||||
int device_count;
|
int device_count;
|
||||||
char vendor[256], product[256], serial[256];
|
char vendor[256], product[256], serial[256];
|
||||||
|
|
@ -199,6 +202,9 @@ void modesInitRTLSDR(void) {
|
||||||
device_count = rtlsdr_get_device_count();
|
device_count = rtlsdr_get_device_count();
|
||||||
if (!device_count) {
|
if (!device_count) {
|
||||||
fprintf(stderr, "No supported RTLSDR devices found.\n");
|
fprintf(stderr, "No supported RTLSDR devices found.\n");
|
||||||
|
if (Modes.no_rtlsdr_ok) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,6 +246,7 @@ void modesInitRTLSDR(void) {
|
||||||
rtlsdr_reset_buffer(Modes.dev);
|
rtlsdr_reset_buffer(Modes.dev);
|
||||||
fprintf(stderr, "Gain reported by device: %.2f\n",
|
fprintf(stderr, "Gain reported by device: %.2f\n",
|
||||||
rtlsdr_get_tuner_gain(Modes.dev)/10.0);
|
rtlsdr_get_tuner_gain(Modes.dev)/10.0);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
@ -409,16 +416,19 @@ void showHelp(void) {
|
||||||
"--modeac Enable decoding of SSR Modes 3/A & 3/C\n"
|
"--modeac Enable decoding of SSR Modes 3/A & 3/C\n"
|
||||||
"--net-beast TCP raw output in Beast binary format\n"
|
"--net-beast TCP raw output in Beast binary format\n"
|
||||||
"--net-only Enable just networking, no RTL device or file used\n"
|
"--net-only Enable just networking, no RTL device or file used\n"
|
||||||
|
"--no-rtlsdr-ok Keep going even if no RTLSDR device is found\n"
|
||||||
|
"--net-fatsv-port <port> FlightAware TSV output port (default: 10001)\n"
|
||||||
"--net-http-port <port> HTTP server port (default: 8080)\n"
|
"--net-http-port <port> HTTP server port (default: 8080)\n"
|
||||||
"--net-ri-port <port> TCP raw input listen port (default: 30001)\n"
|
"--net-ri-port <port> TCP raw input listen port (default: 30001)\n"
|
||||||
"--net-ro-port <port> TCP raw output listen port (default: 30002)\n"
|
"--net-ro-port <port> TCP raw output listen port (default: 30002)\n"
|
||||||
"--net-sbs-port <port> TCP BaseStation output listen port (default: 30003)\n"
|
"--net-sbs-port <port> TCP BaseStation output listen port (default: 30003)\n"
|
||||||
"--net-bi-port <port> TCP Beast input listen port (default: 30004)\n"
|
"--net-bi-port <port> TCP Beast input listen port (default: 30104)\n"
|
||||||
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
|
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
|
||||||
"--net-ro-size <size> TCP raw output minimum size (default: 0)\n"
|
"--net-ro-size <size> TCP raw output minimum size (default: 0)\n"
|
||||||
"--net-ro-rate <rate> TCP raw output memory flush rate (default: 0)\n"
|
"--net-ro-rate <rate> TCP raw output memory flush rate (default: 0)\n"
|
||||||
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
|
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
|
||||||
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
|
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
|
||||||
|
"--forward-mlat Allow forwarding of received mlat results to output ports\n"
|
||||||
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
|
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
|
||||||
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
|
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
|
||||||
"--fix Enable single-bits error correction using CRC\n"
|
"--fix Enable single-bits error correction using CRC\n"
|
||||||
|
|
@ -573,6 +583,7 @@ void backgroundTasks(void) {
|
||||||
|
|
||||||
if (Modes.net) {
|
if (Modes.net) {
|
||||||
modesReadFromClients();
|
modesReadFromClients();
|
||||||
|
showFlightsFATSV();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Modes.aircrafts is not NULL, remove any stale aircraft
|
// If Modes.aircrafts is not NULL, remove any stale aircraft
|
||||||
|
|
@ -699,6 +710,8 @@ int main(int argc, char **argv) {
|
||||||
} else if (!strcmp(argv[j],"--net-only")) {
|
} else if (!strcmp(argv[j],"--net-only")) {
|
||||||
Modes.net = 1;
|
Modes.net = 1;
|
||||||
Modes.net_only = 1;
|
Modes.net_only = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--no-rtlsdr-ok")) {
|
||||||
|
Modes.no_rtlsdr_ok = 1;
|
||||||
} else if (!strcmp(argv[j],"--net-heartbeat") && more) {
|
} else if (!strcmp(argv[j],"--net-heartbeat") && more) {
|
||||||
Modes.net_heartbeat_rate = atoi(argv[++j]) * 15;
|
Modes.net_heartbeat_rate = atoi(argv[++j]) * 15;
|
||||||
} else if (!strcmp(argv[j],"--net-ro-size") && more) {
|
} else if (!strcmp(argv[j],"--net-ro-size") && more) {
|
||||||
|
|
@ -718,10 +731,14 @@ int main(int argc, char **argv) {
|
||||||
Modes.net_input_beast_port = atoi(argv[++j]);
|
Modes.net_input_beast_port = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--net-http-port") && more) {
|
} else if (!strcmp(argv[j],"--net-http-port") && more) {
|
||||||
Modes.net_http_port = atoi(argv[++j]);
|
Modes.net_http_port = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--net-fatsv-port") && more) {
|
||||||
|
Modes.net_fatsv_port = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--net-sbs-port") && more) {
|
} else if (!strcmp(argv[j],"--net-sbs-port") && more) {
|
||||||
Modes.net_output_sbs_port = atoi(argv[++j]);
|
Modes.net_output_sbs_port = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--net-buffer") && more) {
|
} else if (!strcmp(argv[j],"--net-buffer") && more) {
|
||||||
Modes.net_sndbuf_size = atoi(argv[++j]);
|
Modes.net_sndbuf_size = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--forward-mlat")) {
|
||||||
|
Modes.forward_mlat = 1;
|
||||||
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
||||||
Modes.onlyaddr = 1;
|
Modes.onlyaddr = 1;
|
||||||
} else if (!strcmp(argv[j],"--metric")) {
|
} else if (!strcmp(argv[j],"--metric")) {
|
||||||
|
|
@ -800,7 +817,10 @@ int main(int argc, char **argv) {
|
||||||
if (Modes.net_only) {
|
if (Modes.net_only) {
|
||||||
fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
|
fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
|
||||||
} else if (Modes.filename == NULL) {
|
} else if (Modes.filename == NULL) {
|
||||||
modesInitRTLSDR();
|
if (!modesInitRTLSDR()) {
|
||||||
|
// no RTLSDR found and --no-rtlsdr-ok specified, proceed net-only
|
||||||
|
Modes.net_only = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
|
if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
|
||||||
Modes.fd = STDIN_FILENO;
|
Modes.fd = STDIN_FILENO;
|
||||||
|
|
@ -899,3 +919,5 @@ int main(int argc, char **argv) {
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
33
dump1090.h
33
dump1090.h
|
|
@ -37,7 +37,9 @@
|
||||||
// MinorVer changes when additional features are added, but not for bug fixes (range 00-99)
|
// MinorVer changes when additional features are added, but not for bug fixes (range 00-99)
|
||||||
// DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update
|
// DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update
|
||||||
//
|
//
|
||||||
|
#ifndef MODES_DUMP1090_VERSION
|
||||||
#define MODES_DUMP1090_VERSION "1.09.0608.14"
|
#define MODES_DUMP1090_VERSION "1.09.0608.14"
|
||||||
|
#endif
|
||||||
|
|
||||||
// ============================= Include files ==========================
|
// ============================= Include files ==========================
|
||||||
|
|
||||||
|
|
@ -57,11 +59,9 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include "rtl-sdr.h"
|
|
||||||
#include "anet.h"
|
#include "anet.h"
|
||||||
#else
|
#else
|
||||||
#include "winstubs.h" //Put everything Windows specific in here
|
#include "winstubs.h" //Put everything Windows specific in here
|
||||||
#include "rtl-sdr.h"
|
|
||||||
#include "anet.h"
|
#include "anet.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -143,6 +143,7 @@
|
||||||
#define MODES_ACFLAGS_FS_VALID (1<<13) // Aircraft Flight Status is known
|
#define MODES_ACFLAGS_FS_VALID (1<<13) // Aircraft Flight Status is known
|
||||||
#define MODES_ACFLAGS_NSEWSPD_VALID (1<<14) // Aircraft EW and NS Speed is known
|
#define MODES_ACFLAGS_NSEWSPD_VALID (1<<14) // Aircraft EW and NS Speed is known
|
||||||
#define MODES_ACFLAGS_LATLON_REL_OK (1<<15) // Indicates it's OK to do a relative CPR
|
#define MODES_ACFLAGS_LATLON_REL_OK (1<<15) // Indicates it's OK to do a relative CPR
|
||||||
|
#define MODES_ACFLAGS_MLAT (1<<16) // Position is from mlat
|
||||||
|
|
||||||
#define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
|
#define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
|
||||||
#define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
|
#define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
|
||||||
|
|
@ -167,13 +168,14 @@
|
||||||
|
|
||||||
#define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min
|
#define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min
|
||||||
|
|
||||||
#define MODES_NET_SERVICES_NUM 6
|
#define MODES_NET_SERVICES_NUM 7
|
||||||
#define MODES_NET_INPUT_RAW_PORT 30001
|
#define MODES_NET_INPUT_RAW_PORT 30001
|
||||||
#define MODES_NET_OUTPUT_RAW_PORT 30002
|
#define MODES_NET_OUTPUT_RAW_PORT 30002
|
||||||
#define MODES_NET_OUTPUT_SBS_PORT 30003
|
#define MODES_NET_OUTPUT_SBS_PORT 30003
|
||||||
#define MODES_NET_INPUT_BEAST_PORT 30004
|
#define MODES_NET_INPUT_BEAST_PORT 30104
|
||||||
#define MODES_NET_OUTPUT_BEAST_PORT 30005
|
#define MODES_NET_OUTPUT_BEAST_PORT 30005
|
||||||
#define MODES_NET_HTTP_PORT 8080
|
#define MODES_NET_HTTP_PORT 8080
|
||||||
|
#define MODES_NET_OUTPUT_FA_TSV_PORT 10001
|
||||||
#define MODES_CLIENT_BUF_SIZE 1024
|
#define MODES_CLIENT_BUF_SIZE 1024
|
||||||
#define MODES_NET_SNDBUF_SIZE (1024*64)
|
#define MODES_NET_SNDBUF_SIZE (1024*64)
|
||||||
#define MODES_NET_SNDBUF_MAX (7)
|
#define MODES_NET_SNDBUF_MAX (7)
|
||||||
|
|
@ -186,6 +188,10 @@
|
||||||
|
|
||||||
//======================== structure declarations =========================
|
//======================== structure declarations =========================
|
||||||
|
|
||||||
|
// forward declaration of RTL-SDR device struct to avoid a dependency
|
||||||
|
// on RTL-SDR for those utils that don't actually use it
|
||||||
|
typedef struct rtlsdr_dev rtlsdr_dev_t;
|
||||||
|
|
||||||
// Structure used to describe a networking client
|
// Structure used to describe a networking client
|
||||||
struct client {
|
struct client {
|
||||||
struct client* next; // Pointer to next client
|
struct client* next; // Pointer to next client
|
||||||
|
|
@ -193,6 +199,7 @@ struct client {
|
||||||
int service; // TCP port the client is connected to
|
int service; // TCP port the client is connected to
|
||||||
int buflen; // Amount of data on buffer
|
int buflen; // Amount of data on buffer
|
||||||
char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
|
char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
|
||||||
|
char tsvVerbatim[MODES_CLIENT_BUF_SIZE+1]; // data to be quoted in TSV out
|
||||||
};
|
};
|
||||||
|
|
||||||
// Structure used to describe an aircraft in iteractive mode
|
// Structure used to describe an aircraft in iteractive mode
|
||||||
|
|
@ -215,6 +222,10 @@ struct aircraft {
|
||||||
long modeCcount; // Mode C Altitude hit Count
|
long modeCcount; // Mode C Altitude hit Count
|
||||||
int modeACflags; // Flags for mode A/C recognition
|
int modeACflags; // Flags for mode A/C recognition
|
||||||
|
|
||||||
|
int fatsv_emitted_altitude; // last FA emitted altitude
|
||||||
|
int fatsv_emitted_track; // last FA emitted angle of flight
|
||||||
|
time_t fatsv_last_emitted; // time aircraft was last FA emitted
|
||||||
|
|
||||||
// Encoded latitude and longitude as extracted by odd and even CPR encoded messages
|
// Encoded latitude and longitude as extracted by odd and even CPR encoded messages
|
||||||
int odd_cprlat;
|
int odd_cprlat;
|
||||||
int odd_cprlon;
|
int odd_cprlon;
|
||||||
|
|
@ -224,6 +235,7 @@ struct aircraft {
|
||||||
uint64_t even_cprtime;
|
uint64_t even_cprtime;
|
||||||
double lat, lon; // Coordinated obtained from CPR encoded data
|
double lat, lon; // Coordinated obtained from CPR encoded data
|
||||||
int bFlags; // Flags related to valid fields in this structure
|
int bFlags; // Flags related to valid fields in this structure
|
||||||
|
struct client *tsvClient; // client that was last source for this
|
||||||
struct aircraft *next; // Next aircraft in our linked list
|
struct aircraft *next; // Next aircraft in our linked list
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -271,6 +283,7 @@ struct { // Internal state
|
||||||
char aneterr[ANET_ERR_LEN];
|
char aneterr[ANET_ERR_LEN];
|
||||||
struct client *clients; // Our clients
|
struct client *clients; // Our clients
|
||||||
int sbsos; // SBS output listening socket
|
int sbsos; // SBS output listening socket
|
||||||
|
int fatsvos; // FlightAware TSV listening socket
|
||||||
int ros; // Raw output listening socket
|
int ros; // Raw output listening socket
|
||||||
int ris; // Raw input listening socket
|
int ris; // Raw input listening socket
|
||||||
int bos; // Beast output listening socket
|
int bos; // Beast output listening socket
|
||||||
|
|
@ -306,7 +319,10 @@ struct { // Internal state
|
||||||
int net_output_beast_port; // Beast output TCP port
|
int net_output_beast_port; // Beast output TCP port
|
||||||
int net_input_beast_port; // Beast input TCP port
|
int net_input_beast_port; // Beast input TCP port
|
||||||
int net_http_port; // HTTP port
|
int net_http_port; // HTTP port
|
||||||
|
int net_fatsv_port; // FlightAware TSV port
|
||||||
|
int no_rtlsdr_ok; // keep going if no RTLSDR dev found
|
||||||
int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n)
|
int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n)
|
||||||
|
int forward_mlat; // enable forwarding of mlat to output ports
|
||||||
int quiet; // Suppress stdout
|
int quiet; // Suppress stdout
|
||||||
int interactive; // Interactive mode
|
int interactive; // Interactive mode
|
||||||
int interactive_rows; // Interactive mode: max number of rows
|
int interactive_rows; // Interactive mode: max number of rows
|
||||||
|
|
@ -349,8 +365,10 @@ struct { // Internal state
|
||||||
|
|
||||||
unsigned int stat_http_requests;
|
unsigned int stat_http_requests;
|
||||||
unsigned int stat_sbs_connections;
|
unsigned int stat_sbs_connections;
|
||||||
|
unsigned int stat_fatsv_connections;
|
||||||
unsigned int stat_raw_connections;
|
unsigned int stat_raw_connections;
|
||||||
unsigned int stat_beast_connections;
|
unsigned int stat_beast_connections;
|
||||||
|
unsigned int stat_beast_connections_in;
|
||||||
unsigned int stat_out_of_phase;
|
unsigned int stat_out_of_phase;
|
||||||
unsigned int stat_ph_demodulated0;
|
unsigned int stat_ph_demodulated0;
|
||||||
unsigned int stat_ph_demodulated1;
|
unsigned int stat_ph_demodulated1;
|
||||||
|
|
@ -434,7 +452,7 @@ int ModeAToModeC (unsigned int ModeA);
|
||||||
void detectModeS (uint16_t *m, uint32_t mlen);
|
void detectModeS (uint16_t *m, uint32_t mlen);
|
||||||
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
|
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
|
||||||
void displayModesMessage(struct modesMessage *mm);
|
void displayModesMessage(struct modesMessage *mm);
|
||||||
void useModesMessage (struct modesMessage *mm);
|
void useModesMessage (struct modesMessage *mm, struct client *c);
|
||||||
void computeMagnitudeVector(uint16_t *pData);
|
void computeMagnitudeVector(uint16_t *pData);
|
||||||
int decodeCPR (struct aircraft *a, int fflag, int surface);
|
int decodeCPR (struct aircraft *a, int fflag, int surface);
|
||||||
int decodeCPRrelative (struct aircraft *a, int fflag, int surface);
|
int decodeCPRrelative (struct aircraft *a, int fflag, int surface);
|
||||||
|
|
@ -442,7 +460,7 @@ void modesInitErrorInfo ();
|
||||||
//
|
//
|
||||||
// Functions exported from interactive.c
|
// Functions exported from interactive.c
|
||||||
//
|
//
|
||||||
struct aircraft* interactiveReceiveData(struct modesMessage *mm);
|
struct aircraft* interactiveReceiveData(struct modesMessage *mm, struct client *c);
|
||||||
void interactiveShowData(void);
|
void interactiveShowData(void);
|
||||||
void interactiveRemoveStaleAircrafts(void);
|
void interactiveRemoveStaleAircrafts(void);
|
||||||
int decodeBinMessage (struct client *c, char *p);
|
int decodeBinMessage (struct client *c, char *p);
|
||||||
|
|
@ -457,9 +475,12 @@ void modesReadFromClients (void);
|
||||||
void modesSendAllClients (int service, void *msg, int len);
|
void modesSendAllClients (int service, void *msg, int len);
|
||||||
void modesQueueOutput (struct modesMessage *mm);
|
void modesQueueOutput (struct modesMessage *mm);
|
||||||
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
|
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
|
||||||
|
void showFlightsFATSV(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __DUMP1090_H
|
#endif // __DUMP1090_H
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
#!/bin/bash
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
#
|
||||||
|
# Provides: dump1090
|
||||||
|
# Required-Start: $remote_fs
|
||||||
|
# Required-Stop: $remote_fs
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: dump1090 initscript
|
||||||
|
#
|
||||||
|
### END INIT INFO
|
||||||
|
# Fill in name of program here.
|
||||||
|
PROG_ARGS="--quiet --net --gain -10 --net-fatsv-port 0"
|
||||||
|
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
DAEMON=/usr/bin/dump1090
|
||||||
|
PIDFILE=/var/run/dump1090.pid
|
||||||
|
|
||||||
|
test -x $DAEMON || exit 5
|
||||||
|
|
||||||
|
LOCKFILE=/var/lock/dump1090
|
||||||
|
|
||||||
|
start() {
|
||||||
|
log_daemon_msg "Starting dump1090 server" "dump1090"
|
||||||
|
# --quiet
|
||||||
|
/sbin/start-stop-daemon --start --oknodo --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- $PROG_ARGS
|
||||||
|
status=$?
|
||||||
|
log_begin_msg $status
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
log_daemon_msg "Stopping dump1090 server" "dump1090"
|
||||||
|
/sbin/start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
|
||||||
|
log_end_msg $?
|
||||||
|
rm -f $PIDFILE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
echo "no status yet"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
restart|force-reload)
|
||||||
|
stop && sleep 2 && start
|
||||||
|
;;
|
||||||
|
reload)
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status_of_proc $DAEMON "dump1090 server"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
@ -0,0 +1,443 @@
|
||||||
|
// dump1090, a Mode S messages decoder for RTLSDR devices.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
|
||||||
|
// Copyright (C) 2014 by FlightAware LLC
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
#include "faup1090.h"
|
||||||
|
//
|
||||||
|
// ============================= Utility functions ==========================
|
||||||
|
//
|
||||||
|
void sigintHandler(int dummy) {
|
||||||
|
MODES_NOTUSED(dummy);
|
||||||
|
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
|
||||||
|
Modes.exit = 1; // Signal to threads that we are done
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// =============================== Terminal handling ========================
|
||||||
|
//
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Get the number of rows after the terminal changes size.
|
||||||
|
int getTermRows() {
|
||||||
|
struct winsize w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
return (w.ws_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle resizing terminal
|
||||||
|
void sigWinchCallback() {
|
||||||
|
signal(SIGWINCH, SIG_IGN);
|
||||||
|
Modes.interactive_rows = getTermRows();
|
||||||
|
interactiveShowData();
|
||||||
|
signal(SIGWINCH, sigWinchCallback);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int getTermRows() { return MODES_INTERACTIVE_ROWS;}
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// =============================== Initialization ===========================
|
||||||
|
//
|
||||||
|
void modesInitConfig(void) {
|
||||||
|
// Default everything to zero/NULL
|
||||||
|
memset(&Modes, 0, sizeof(Modes));
|
||||||
|
|
||||||
|
// Now initialise things that should not be 0/NULL to their defaults
|
||||||
|
Modes.check_crc = 1;
|
||||||
|
Modes.net = 1;
|
||||||
|
Modes.quiet = 1;
|
||||||
|
Modes.net_heartbeat_rate = MODES_NET_HEARTBEAT_RATE;
|
||||||
|
|
||||||
|
// zero port numbers are ignored and we don't use this stuff.
|
||||||
|
// these assignments aren't even necessary because of the memset
|
||||||
|
// but it's kind of nice to see them here
|
||||||
|
Modes.net_output_sbs_port = 0;
|
||||||
|
Modes.net_output_raw_port = 0;
|
||||||
|
Modes.net_input_raw_port = 0;
|
||||||
|
Modes.net_input_beast_port = 0;
|
||||||
|
Modes.net_output_beast_port = 0;
|
||||||
|
Modes.net_http_port = 0;
|
||||||
|
Modes.no_rtlsdr_ok = 0;
|
||||||
|
|
||||||
|
Modes.net_input_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
|
||||||
|
Modes.net_fatsv_port = MODES_NET_OUTPUT_FA_TSV_PORT;
|
||||||
|
Modes.interactive_rows = getTermRows();
|
||||||
|
Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL;
|
||||||
|
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
|
||||||
|
Modes.fUserLat = MODES_USER_LATITUDE_DFLT;
|
||||||
|
Modes.fUserLon = MODES_USER_LONGITUDE_DFLT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void faupInitConfig(void) {
|
||||||
|
memset(&faup1090, 0, sizeof(faup1090));
|
||||||
|
|
||||||
|
strcpy (faup1090.net_input_beast_ipaddr, FAUP1090_NET_OUTPUT_IP_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
void modesInit(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Allocate the various buffers used by Modes
|
||||||
|
if ( ((Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2) ) == NULL) ||
|
||||||
|
((Modes.beastOut = (char *) malloc(MODES_RAWOUT_BUF_SIZE) ) == NULL) ||
|
||||||
|
((Modes.rawOut = (char *) malloc(MODES_RAWOUT_BUF_SIZE) ) == NULL) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Out of memory allocating data buffer.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the buffers that have just been allocated, just in-case
|
||||||
|
memset(Modes.icao_cache, 0, sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2);
|
||||||
|
|
||||||
|
// Validate the users Lat/Lon home location inputs
|
||||||
|
if ( (Modes.fUserLat > 90.0) // Latitude must be -90 to +90
|
||||||
|
|| (Modes.fUserLat < -90.0) // and
|
||||||
|
|| (Modes.fUserLon > 360.0) // Longitude must be -180 to +360
|
||||||
|
|| (Modes.fUserLon < -180.0) ) {
|
||||||
|
Modes.fUserLat = Modes.fUserLon = 0.0;
|
||||||
|
} else if (Modes.fUserLon > 180.0) { // If Longitude is +180 to +360, make it -180 to 0
|
||||||
|
Modes.fUserLon -= 360.0;
|
||||||
|
}
|
||||||
|
// If both Lat and Lon are 0.0 then the users location is either invalid/not-set, or (s)he's in the
|
||||||
|
// Atlantic ocean off the west coast of Africa. This is unlikely to be correct.
|
||||||
|
// Set the user LatLon valid flag only if either Lat or Lon are non zero. Note the Greenwich meridian
|
||||||
|
// is at 0.0 Lon,so we must check for either fLat or fLon being non zero not both.
|
||||||
|
// Testing the flag at runtime will be much quicker than ((fLon != 0.0) || (fLat != 0.0))
|
||||||
|
Modes.bUserFlags &= ~MODES_USER_LATLON_VALID;
|
||||||
|
if ((Modes.fUserLat != 0.0) || (Modes.fUserLon != 0.0)) {
|
||||||
|
Modes.bUserFlags |= MODES_USER_LATLON_VALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit the maximum requested raw output size to less than one Ethernet Block
|
||||||
|
if (Modes.net_output_raw_size > (MODES_RAWOUT_BUF_FLUSH))
|
||||||
|
{Modes.net_output_raw_size = MODES_RAWOUT_BUF_FLUSH;}
|
||||||
|
if (Modes.net_output_raw_rate > (MODES_RAWOUT_BUF_RATE))
|
||||||
|
{Modes.net_output_raw_rate = MODES_RAWOUT_BUF_RATE;}
|
||||||
|
if (Modes.net_sndbuf_size > (MODES_NET_SNDBUF_MAX))
|
||||||
|
{Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}
|
||||||
|
|
||||||
|
// Initialise the Block Timers to something half sensible
|
||||||
|
ftime(&Modes.stSystemTimeBlk);
|
||||||
|
for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++)
|
||||||
|
{Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;}
|
||||||
|
|
||||||
|
// Prepare error correction tables
|
||||||
|
modesInitErrorInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct service {
|
||||||
|
char *descr;
|
||||||
|
int *socket;
|
||||||
|
int port;
|
||||||
|
int enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct service services[MODES_NET_SERVICES_NUM];
|
||||||
|
|
||||||
|
void faupInitNet(void) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
// for faup1090 only the FlightAware service is enabled.
|
||||||
|
// we need to stick with the same number of services as defined in
|
||||||
|
// dump1090 because dump1090 support routines expect this many.
|
||||||
|
struct service svc[MODES_NET_SERVICES_NUM] = {
|
||||||
|
{"FlightAware TSV output", &Modes.fatsvos, Modes.net_fatsv_port, 1},
|
||||||
|
{"Raw TCP output", &Modes.ros, Modes.net_output_raw_port, 0},
|
||||||
|
{"Raw TCP input", &Modes.ris, Modes.net_input_raw_port, 0},
|
||||||
|
{"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 0},
|
||||||
|
{"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 0},
|
||||||
|
{"HTTP server", &Modes.https, Modes.net_http_port, 0},
|
||||||
|
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&services, &svc, sizeof(svc));//services = svc;
|
||||||
|
|
||||||
|
Modes.clients = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if ( (!Modes.wsaData.wVersion)
|
||||||
|
&& (!Modes.wsaData.wHighVersion) ) {
|
||||||
|
// Try to start the windows socket support
|
||||||
|
if (WSAStartup(MAKEWORD(2,1),&Modes.wsaData) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "WSAStartup returned Error\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
|
||||||
|
// printf("initialize service %d (%s), port %d, enabled %d\n", j, services[j].descr, services[j].port, services[j].enabled);
|
||||||
|
|
||||||
|
// why flip the enabled bit on if a port is nonzero?
|
||||||
|
// just use the enabled bit as set in the svc structure.
|
||||||
|
// this way the port we connect to as faup1090 (30005) is there
|
||||||
|
// services[j].enabled = (services[j].port != 0);
|
||||||
|
if (services[j].enabled) {
|
||||||
|
int s = anetTcpServer(Modes.aneterr, services[j].port, NULL);
|
||||||
|
if (s == -1) {
|
||||||
|
fprintf(stderr, "faup1090: error opening the listening port %d (%s): %s\n",
|
||||||
|
services[j].port, services[j].descr, strerror(errno));
|
||||||
|
if (errno == EADDRINUSE) {
|
||||||
|
exit(98);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
anetNonBlock(Modes.aneterr, s);
|
||||||
|
*services[j].socket = s;
|
||||||
|
} else {
|
||||||
|
if (Modes.debug & MODES_DEBUG_NET) printf("%s port is disabled\n", services[j].descr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ================================ Main ====================================
|
||||||
|
//
|
||||||
|
void showHelp(void) {
|
||||||
|
printf(
|
||||||
|
"-----------------------------------------------------------------------------\n"
|
||||||
|
"| FlightAware faup1090 Ver : "FAUP1090_VERSION " |\n"
|
||||||
|
"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n"
|
||||||
|
"-----------------------------------------------------------------------------\n"
|
||||||
|
"--interactive Interactive mode refreshing data on screen\n"
|
||||||
|
"--interactive-rows <num> Max number of rows in interactive mode (default: 15)\n"
|
||||||
|
"--interactive-ttl <sec> Remove from list if idle for <sec> (default: 60)\n"
|
||||||
|
"--interactive-rtl1090 Display flight table in RTL1090 format\n"
|
||||||
|
"--net-fatsv-port <port> FlightAware TSV output port (default: 10001)\n"
|
||||||
|
"--net-bo-ipaddr <IPv4> TCP Beast output listen IPV4 address (default: 127.0.0.1)\n"
|
||||||
|
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
|
||||||
|
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
|
||||||
|
"--no-crc-check Enable messages with broken CRC (discouraged)\n"
|
||||||
|
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
|
||||||
|
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
|
||||||
|
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
|
||||||
|
"--debug <flags> Debug mode (verbose), see README for details\n"
|
||||||
|
"--quiet Disable output to stdout. Use for daemon applications\n"
|
||||||
|
"--help Show this help\n"
|
||||||
|
"\n"
|
||||||
|
"Debug mode flags: n = Log network debugging info\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void showCopyright(void) {
|
||||||
|
uint64_t llTime = time(NULL) + 1;
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"-----------------------------------------------------------------------------\n"
|
||||||
|
"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n"
|
||||||
|
"-----------------------------------------------------------------------------\n"
|
||||||
|
"\n"
|
||||||
|
" Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>\n"
|
||||||
|
" Copyright (C) 2014 by Malcolm Robb <support@attavionics.com>\n"
|
||||||
|
" Copyright (C) 2014 by FlightAware LLC\n"
|
||||||
|
"\n"
|
||||||
|
" All rights reserved.\n"
|
||||||
|
"\n"
|
||||||
|
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
|
||||||
|
" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
|
||||||
|
" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
|
||||||
|
" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
|
||||||
|
" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
|
||||||
|
" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
|
||||||
|
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
|
||||||
|
" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
|
||||||
|
" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
|
||||||
|
" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
|
||||||
|
" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
|
||||||
|
"\n"
|
||||||
|
" For further details refer to <https://github.com/MalcolmRobb/dump1090>\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
// delay for 1 second to give the user a chance to read the copyright
|
||||||
|
while (llTime >= time(NULL)) {}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
// This function is called a few times every second by main in order to
|
||||||
|
// perform tasks we need to do continuously, like accepting new clients
|
||||||
|
// from the net, refreshing the screen in interactive mode, and so forth
|
||||||
|
//
|
||||||
|
void backgroundTasks(void) {
|
||||||
|
if (Modes.net) {
|
||||||
|
modesReadFromClients();
|
||||||
|
showFlightsFATSV();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Modes.aircrafts is not NULL, remove any stale aircraft
|
||||||
|
if (Modes.aircrafts) {
|
||||||
|
interactiveRemoveStaleAircrafts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh screen when in interactive mode
|
||||||
|
if (Modes.interactive) {
|
||||||
|
interactiveShowData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have lost our input connection, exit
|
||||||
|
if (Modes.stat_beast_connections_in == 0) {
|
||||||
|
fprintf(stderr, "Lost ADS-B data connection, exiting.\n");
|
||||||
|
Modes.exit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int j, fd;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
// Set sane defaults
|
||||||
|
modesInitConfig();
|
||||||
|
faupInitConfig();
|
||||||
|
signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)
|
||||||
|
|
||||||
|
// Parse the command line options
|
||||||
|
for (j = 1; j < argc; j++) {
|
||||||
|
int more = j+1 < argc; // There are more arguments
|
||||||
|
|
||||||
|
if (!strcmp(argv[j],"--no-crc-check")) {
|
||||||
|
Modes.check_crc = 0;
|
||||||
|
} else if (!strcmp(argv[j],"--net-heartbeat") && more) {
|
||||||
|
Modes.net_heartbeat_rate = atoi(argv[++j]) * 15;
|
||||||
|
} else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) {
|
||||||
|
strcpy (faup1090.net_input_beast_ipaddr, argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--net-bo-port") && more) {
|
||||||
|
Modes.net_input_beast_port = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--net-fatsv-port") && more) {
|
||||||
|
Modes.net_fatsv_port = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--net-buffer") && more) {
|
||||||
|
Modes.net_sndbuf_size = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
||||||
|
Modes.onlyaddr = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--interactive")) {
|
||||||
|
Modes.interactive = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--interactive-rows") && more) {
|
||||||
|
Modes.interactive_rows = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--interactive-ttl") && more) {
|
||||||
|
Modes.interactive_display_ttl = atoi(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--lat") && more) {
|
||||||
|
Modes.fUserLat = atof(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--lon") && more) {
|
||||||
|
Modes.fUserLon = atof(argv[++j]);
|
||||||
|
} else if (!strcmp(argv[j],"--debug") && more) {
|
||||||
|
char *f = argv[++j];
|
||||||
|
while(*f) {
|
||||||
|
switch(*f) {
|
||||||
|
case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break;
|
||||||
|
case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break;
|
||||||
|
case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break;
|
||||||
|
case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break;
|
||||||
|
case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break;
|
||||||
|
case 'n': Modes.debug |= MODES_DEBUG_NET; break;
|
||||||
|
case 'j': Modes.debug |= MODES_DEBUG_JS; break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown debugging flag: %c\n", *f);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[j],"--stats")) {
|
||||||
|
Modes.stats = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--help")) {
|
||||||
|
showHelp();
|
||||||
|
exit(0);
|
||||||
|
} else if (!strcmp(argv[j],"--quiet")) {
|
||||||
|
Modes.quiet = 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unknown or not enough arguments for option '%s'.\n\n",
|
||||||
|
argv[j]);
|
||||||
|
showHelp();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Try to comply with the Copyright license conditions for binary distribution
|
||||||
|
if (!Modes.quiet) {showCopyright();}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Setup for SIGWINCH for handling lines
|
||||||
|
if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
modesInit();
|
||||||
|
|
||||||
|
Modes.net_only = 1;
|
||||||
|
|
||||||
|
faupInitNet();
|
||||||
|
|
||||||
|
if ((fd = anetTcpConnect (Modes.aneterr, faup1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) {
|
||||||
|
fprintf (stderr, "faup1090: failed to connect to %s:%d (is dump1090 running?)\n", faup1090.net_input_beast_ipaddr, Modes.net_input_beast_port);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = (struct client *) malloc(sizeof(*c));
|
||||||
|
c->next = NULL;
|
||||||
|
c->buflen = 0;
|
||||||
|
c->fd =
|
||||||
|
c->service =
|
||||||
|
Modes.bis = fd;
|
||||||
|
c->tsvVerbatim[0] = 0;
|
||||||
|
Modes.clients = c;
|
||||||
|
Modes.stat_beast_connections_in = 1;
|
||||||
|
|
||||||
|
while (Modes.net_only) {
|
||||||
|
if (Modes.exit) exit(0); // If we exit net_only nothing further in main()
|
||||||
|
backgroundTasks();
|
||||||
|
usleep(100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Modes.exit == 0) {
|
||||||
|
backgroundTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
pthread_exit(0);
|
||||||
|
#else
|
||||||
|
return (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include "dump1090.h"
|
||||||
|
|
||||||
|
#define FAUP1090_VERSION "1.20"
|
||||||
|
|
||||||
|
#undef MODES_NET_INPUT_RAW_PORT
|
||||||
|
#define MODES_NET_INPUT_RAW_PORT 0
|
||||||
|
|
||||||
|
#undef MODES_NET_INPUT_BEAST_PORT
|
||||||
|
#define MODES_NET_INPUT_BEAST_PORT 0
|
||||||
|
|
||||||
|
#undef MODES_NET_OUTPUT_FA_TSV_PORT
|
||||||
|
#define MODES_NET_OUTPUT_FA_TSV_PORT 10001
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char net_input_beast_ipaddr[32];
|
||||||
|
} faup1090;
|
||||||
|
|
||||||
|
#define FAUP1090_NET_OUTPUT_IP_ADDRESS "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -256,7 +256,7 @@ void interactiveUpdateAircraftModeS() {
|
||||||
//
|
//
|
||||||
// Receive new messages and populate the interactive mode with more info
|
// Receive new messages and populate the interactive mode with more info
|
||||||
//
|
//
|
||||||
struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
struct aircraft *interactiveReceiveData(struct modesMessage *mm, struct client *c) {
|
||||||
struct aircraft *a, *aux;
|
struct aircraft *a, *aux;
|
||||||
|
|
||||||
// Return if (checking crc) AND (not crcok) AND (not fixed)
|
// Return if (checking crc) AND (not crcok) AND (not fixed)
|
||||||
|
|
@ -292,6 +292,7 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
||||||
a->seen = time(NULL);
|
a->seen = time(NULL);
|
||||||
a->timestamp = mm->timestampMsg;
|
a->timestamp = mm->timestampMsg;
|
||||||
a->messages++;
|
a->messages++;
|
||||||
|
a->tsvClient = c;
|
||||||
|
|
||||||
// If a (new) CALLSIGN has been received, copy it to the aircraft structure
|
// If a (new) CALLSIGN has been received, copy it to the aircraft structure
|
||||||
if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {
|
if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {
|
||||||
|
|
@ -370,6 +371,8 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
||||||
//If we sucessfully decoded, back copy the results to mm so that we can print them in list output
|
//If we sucessfully decoded, back copy the results to mm so that we can print them in list output
|
||||||
if (location_ok) {
|
if (location_ok) {
|
||||||
mm->bFlags |= MODES_ACFLAGS_LATLON_VALID;
|
mm->bFlags |= MODES_ACFLAGS_LATLON_VALID;
|
||||||
|
if (!(mm->bFlags & MODES_ACFLAGS_MLAT))
|
||||||
|
a->bFlags &= ~MODES_ACFLAGS_MLAT;
|
||||||
mm->fLat = a->lat;
|
mm->fLat = a->lat;
|
||||||
mm->fLon = a->lon;
|
mm->fLon = a->lon;
|
||||||
}
|
}
|
||||||
|
|
@ -559,3 +562,5 @@ void interactiveRemoveStaleAircrafts(void) {
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
#
|
||||||
|
# When building a package or installing otherwise in the system, make
|
||||||
|
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
||||||
|
#
|
||||||
|
PROGNAME=faup1090
|
||||||
|
DUMP1090=dump1090
|
||||||
|
|
||||||
|
include /usr/share/dpkg/buildflags.mk
|
||||||
|
|
||||||
|
PREFIX=/usr
|
||||||
|
|
||||||
|
ifdef PREFIX
|
||||||
|
BINDIR=$(PREFIX)/bin
|
||||||
|
SHAREDIR=$(PREFIX)/share/$(DUMP1090)
|
||||||
|
HTMLDIR=$(SHAREDIR)/public_html
|
||||||
|
EXTRACFLAGS=-DHTMLPATH=\"$(HTMLDIR)\"
|
||||||
|
endif
|
||||||
|
|
||||||
|
#CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
||||||
|
#CFLAGS+=-Wall -W `pkg-config --cflags librtlsdr`
|
||||||
|
CFLAGS+=-Wall -W
|
||||||
|
#LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
|
||||||
|
LIBS=-lpthread -lm
|
||||||
|
CC=gcc
|
||||||
|
|
||||||
|
info:
|
||||||
|
@echo "'make all' compile faup1090"
|
||||||
|
@echo "'make install-faup1090' install faup1090"
|
||||||
|
@echo "'make install-dump1090' install dump1090"
|
||||||
|
@echo "'make install-autostart' make dump1090 autostart upon boot"
|
||||||
|
@echo "'make full-install' all of the above"
|
||||||
|
|
||||||
|
all: faup1090
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
|
||||||
|
|
||||||
|
faup1090.o: faup1090.c faup1090.h
|
||||||
|
|
||||||
|
faup1090: faup1090.o
|
||||||
|
|
||||||
|
faup1090: faup1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
|
||||||
|
$(CC) $(LDFLAGS) -g -o faup1090 faup1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o faup1090
|
||||||
|
|
||||||
|
install-faup1090: faup1090
|
||||||
|
install $(PROGNAME) $(BINDIR)
|
||||||
|
|
||||||
|
install-dump1090:
|
||||||
|
install $(DUMP1090) $(BINDIR)
|
||||||
|
mkdir -p $(HTMLDIR)
|
||||||
|
cp -R public_html $(SHAREDIR)
|
||||||
|
|
||||||
|
install-autostart:
|
||||||
|
install fadump1090.sh /etc/init.d/
|
||||||
|
update-rc.d fadump1090.sh defaults
|
||||||
|
|
||||||
|
full-install: install-faup1090 install-dump1090 install-autostart
|
||||||
|
|
@ -10,8 +10,8 @@ SHAREDIR=$(PREFIX)/share/$(PROGNAME)
|
||||||
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
CFLAGS=-O2 -g -Wall -W
|
||||||
LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
|
LIBS=-lpthread -lm
|
||||||
CC=gcc
|
CC=gcc
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ SHAREDIR=$(PREFIX)/share/$(PROGNAME)
|
||||||
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
CFLAGS=-O2 -g -Wall -W
|
||||||
LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
|
LIBS=-lpthread -lm
|
||||||
CC=gcc
|
CC=gcc
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -384,3 +384,5 @@ void decodeModeAMessage(struct modesMessage *mm, int ModeA)
|
||||||
//
|
//
|
||||||
// ===================== Mode A/C detection and decoding ===================
|
// ===================== Mode A/C detection and decoding ===================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
13
mode_s.c
13
mode_s.c
|
|
@ -838,6 +838,9 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
||||||
memcpy(mm->msg, msg, MODES_LONG_MSG_BYTES);
|
memcpy(mm->msg, msg, MODES_LONG_MSG_BYTES);
|
||||||
msg = mm->msg;
|
msg = mm->msg;
|
||||||
|
|
||||||
|
if (mm->remote && mm->timestampMsg == 0xFF004D4C4154) // Magic mlat timestamp
|
||||||
|
mm->bFlags |= MODES_ACFLAGS_MLAT;
|
||||||
|
|
||||||
// Get the message type ASAP as other operations depend on this
|
// Get the message type ASAP as other operations depend on this
|
||||||
mm->msgtype = msg[0] >> 3; // Downlink Format
|
mm->msgtype = msg[0] >> 3; // Downlink Format
|
||||||
mm->msgbits = modesMessageLenByType(mm->msgtype);
|
mm->msgbits = modesMessageLenByType(mm->msgtype);
|
||||||
|
|
@ -1569,7 +1572,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
decodeModeAMessage(&mm, ModeA);
|
decodeModeAMessage(&mm, ModeA);
|
||||||
|
|
||||||
// Pass data to the next layer
|
// Pass data to the next layer
|
||||||
useModesMessage(&mm);
|
useModesMessage(&mm, NULL);
|
||||||
|
|
||||||
j += MODEAC_MSG_SAMPLES;
|
j += MODEAC_MSG_SAMPLES;
|
||||||
Modes.stat_ModeAC++;
|
Modes.stat_ModeAC++;
|
||||||
|
|
@ -1833,7 +1836,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass data to the next layer
|
// Pass data to the next layer
|
||||||
useModesMessage(&mm);
|
useModesMessage(&mm, NULL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) {
|
if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) {
|
||||||
|
|
@ -1897,11 +1900,11 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
// Basically this function passes a raw message to the upper layers for further
|
// Basically this function passes a raw message to the upper layers for further
|
||||||
// processing and visualization
|
// processing and visualization
|
||||||
//
|
//
|
||||||
void useModesMessage(struct modesMessage *mm) {
|
void useModesMessage(struct modesMessage *mm, struct client *c) {
|
||||||
if ((Modes.check_crc == 0) || (mm->crcok) || (mm->correctedbits)) { // not checking, ok or fixed
|
if ((Modes.check_crc == 0) || (mm->crcok) || (mm->correctedbits)) { // not checking, ok or fixed
|
||||||
|
|
||||||
// Always track aircraft
|
// Always track aircraft
|
||||||
interactiveReceiveData(mm);
|
interactiveReceiveData(mm, c);
|
||||||
|
|
||||||
// In non-interactive non-quiet mode, display messages on standard output
|
// In non-interactive non-quiet mode, display messages on standard output
|
||||||
if (!Modes.interactive && !Modes.quiet) {
|
if (!Modes.interactive && !Modes.quiet) {
|
||||||
|
|
@ -2170,3 +2173,5 @@ int decodeCPRrelative(struct aircraft *a, int fflag, int surface) {
|
||||||
//
|
//
|
||||||
// ===================== Mode S detection and decoding ===================
|
// ===================== Mode S detection and decoding ===================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
281
net_io.c
281
net_io.c
|
|
@ -64,7 +64,8 @@ void modesInitNet(void) {
|
||||||
{"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 1},
|
{"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 1},
|
||||||
{"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 1},
|
{"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 1},
|
||||||
{"HTTP server", &Modes.https, Modes.net_http_port, 1},
|
{"HTTP server", &Modes.https, Modes.net_http_port, 1},
|
||||||
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 1}
|
{"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 1},
|
||||||
|
{"FlightAware TSV output", &Modes.fatsvos, Modes.net_fatsv_port, 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
memcpy(&services, &svc, sizeof(svc));//services = svc;
|
memcpy(&services, &svc, sizeof(svc));//services = svc;
|
||||||
|
|
@ -124,12 +125,15 @@ struct client * modesAcceptClients(void) {
|
||||||
c->next = Modes.clients;
|
c->next = Modes.clients;
|
||||||
c->fd = fd;
|
c->fd = fd;
|
||||||
c->buflen = 0;
|
c->buflen = 0;
|
||||||
|
c->tsvVerbatim[0] = 0;
|
||||||
Modes.clients = c;
|
Modes.clients = c;
|
||||||
anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size));
|
anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size));
|
||||||
|
|
||||||
if (*services[j].socket == Modes.sbsos) Modes.stat_sbs_connections++;
|
if (*services[j].socket == Modes.sbsos) Modes.stat_sbs_connections++;
|
||||||
if (*services[j].socket == Modes.ros) Modes.stat_raw_connections++;
|
if (*services[j].socket == Modes.ros) Modes.stat_raw_connections++;
|
||||||
if (*services[j].socket == Modes.bos) Modes.stat_beast_connections++;
|
if (*services[j].socket == Modes.bos) Modes.stat_beast_connections++;
|
||||||
|
if (*services[j].socket == Modes.bis) Modes.stat_beast_connections_in++;
|
||||||
|
if (*services[j].socket == Modes.fatsvos) Modes.stat_fatsv_connections++;
|
||||||
|
|
||||||
j--; // Try again with the same listening port
|
j--; // Try again with the same listening port
|
||||||
|
|
||||||
|
|
@ -161,20 +165,31 @@ void modesFreeClient(struct client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's now safe to remove this client
|
free(c);
|
||||||
close(c->fd);
|
}
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
||||||
|
// Close the client connection and mark it as closed
|
||||||
|
//
|
||||||
|
void modesCloseClient(struct client *c) {
|
||||||
|
close(c->fd);
|
||||||
if (c->service == Modes.sbsos) {
|
if (c->service == Modes.sbsos) {
|
||||||
if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--;
|
if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--;
|
||||||
} else if (c->service == Modes.ros) {
|
} else if (c->service == Modes.ros) {
|
||||||
if (Modes.stat_raw_connections) Modes.stat_raw_connections--;
|
if (Modes.stat_raw_connections) Modes.stat_raw_connections--;
|
||||||
} else if (c->service == Modes.bos) {
|
} else if (c->service == Modes.bos) {
|
||||||
if (Modes.stat_beast_connections) Modes.stat_beast_connections--;
|
if (Modes.stat_beast_connections) Modes.stat_beast_connections--;
|
||||||
|
} else if (c->service == Modes.bis) {
|
||||||
|
if (Modes.stat_beast_connections_in) Modes.stat_beast_connections_in--;
|
||||||
|
} else if (c->service == Modes.fatsvos) {
|
||||||
|
if (Modes.stat_fatsv_connections) Modes.stat_fatsv_connections--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Modes.debug & MODES_DEBUG_NET)
|
if (Modes.debug & MODES_DEBUG_NET)
|
||||||
printf("Closing client %d\n", c->fd);
|
printf("Closing client %d\n", c->fd);
|
||||||
|
|
||||||
free(c);
|
c->fd = -1;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
@ -188,15 +203,19 @@ void modesSendAllClients(int service, void *msg, int len) {
|
||||||
// Read next before servicing client incase the service routine deletes the client!
|
// Read next before servicing client incase the service routine deletes the client!
|
||||||
struct client *next = c->next;
|
struct client *next = c->next;
|
||||||
|
|
||||||
if (c->service == service) {
|
if (c->fd != -1) {
|
||||||
|
if (c->service == service) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int nwritten = write(c->fd, msg, len);
|
int nwritten = write(c->fd, msg, len);
|
||||||
#else
|
#else
|
||||||
int nwritten = send(c->fd, msg, len, 0 );
|
int nwritten = send(c->fd, msg, len, 0 );
|
||||||
#endif
|
#endif
|
||||||
if (nwritten != len) {
|
if (nwritten != len) {
|
||||||
modesFreeClient(c);
|
modesCloseClient(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
modesFreeClient(c);
|
||||||
}
|
}
|
||||||
c = next;
|
c = next;
|
||||||
}
|
}
|
||||||
|
|
@ -454,6 +473,9 @@ void modesSendSBSOutput(struct modesMessage *mm) {
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
void modesQueueOutput(struct modesMessage *mm) {
|
void modesQueueOutput(struct modesMessage *mm) {
|
||||||
|
if ((mm->bFlags & MODES_ACFLAGS_MLAT) && !Modes.forward_mlat)
|
||||||
|
return;
|
||||||
|
|
||||||
if (Modes.stat_sbs_connections) {modesSendSBSOutput(mm);}
|
if (Modes.stat_sbs_connections) {modesSendSBSOutput(mm);}
|
||||||
if (Modes.stat_beast_connections) {modesSendBeastOutput(mm);}
|
if (Modes.stat_beast_connections) {modesSendBeastOutput(mm);}
|
||||||
if (Modes.stat_raw_connections) {modesSendRawOutput(mm);}
|
if (Modes.stat_raw_connections) {modesSendRawOutput(mm);}
|
||||||
|
|
@ -517,7 +539,7 @@ int decodeBinMessage(struct client *c, char *p) {
|
||||||
decodeModesMessage(&mm, msg);
|
decodeModesMessage(&mm, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
useModesMessage(&mm);
|
useModesMessage(&mm, c);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -554,6 +576,8 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
MODES_NOTUSED(c);
|
MODES_NOTUSED(c);
|
||||||
memset(&mm, 0, sizeof(mm));
|
memset(&mm, 0, sizeof(mm));
|
||||||
|
|
||||||
|
// printf("Decode hex message:%s\n", hex);
|
||||||
|
|
||||||
// Mark messages received over the internet as remote so that we don't try to
|
// Mark messages received over the internet as remote so that we don't try to
|
||||||
// pass them off as being received by this instance when forwarding them
|
// pass them off as being received by this instance when forwarding them
|
||||||
mm.remote = 1;
|
mm.remote = 1;
|
||||||
|
|
@ -563,6 +587,7 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
while(l && isspace(hex[l-1])) {
|
while(l && isspace(hex[l-1])) {
|
||||||
hex[l-1] = '\0'; l--;
|
hex[l-1] = '\0'; l--;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(isspace(*hex)) {
|
while(isspace(*hex)) {
|
||||||
hex++; l--;
|
hex++; l--;
|
||||||
}
|
}
|
||||||
|
|
@ -578,6 +603,11 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ;
|
hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ;
|
||||||
break;}
|
break;}
|
||||||
|
|
||||||
|
// if the preamble is #, copy verbatim string
|
||||||
|
case '#': {
|
||||||
|
strncpy (c->tsvVerbatim, hex+1, l-1);
|
||||||
|
break;}
|
||||||
|
|
||||||
case '@': // No CRC check
|
case '@': // No CRC check
|
||||||
case '%': { // CRC is OK
|
case '%': { // CRC is OK
|
||||||
hex += 13; l -= 14; // Skip @,%, and timestamp, and ;
|
hex += 13; l -= 14; // Skip @,%, and timestamp, and ;
|
||||||
|
|
@ -616,7 +646,7 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
decodeModesMessage(&mm, msg);
|
decodeModesMessage(&mm, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
useModesMessage(&mm);
|
useModesMessage(&mm, c);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
@ -654,9 +684,10 @@ char *aircraftsToJson(int *len) {
|
||||||
l = snprintf(p,buflen,
|
l = snprintf(p,buflen,
|
||||||
"{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, "
|
"{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, "
|
||||||
"\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"vert_rate\":%d,\"track\":%d, \"validtrack\":%d,"
|
"\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"vert_rate\":%d,\"track\":%d, \"validtrack\":%d,"
|
||||||
"\"speed\":%d, \"messages\":%ld, \"seen\":%d},\n",
|
"\"speed\":%d, \"messages\":%ld, \"seen\":%d, \"mlat\":%s},\n",
|
||||||
a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->vert_rate, a->track, track,
|
a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->vert_rate, a->track, track,
|
||||||
a->speed, a->messages, (int)(now - a->seen));
|
a->speed, a->messages, (int)(now - a->seen),
|
||||||
|
(a->bFlags & MODES_ACFLAGS_MLAT) ? "true" : "false");
|
||||||
p += l; buflen -= l;
|
p += l; buflen -= l;
|
||||||
|
|
||||||
//Resize if needed
|
//Resize if needed
|
||||||
|
|
@ -715,11 +746,12 @@ int handleHTTPRequest(struct client *c, char *p) {
|
||||||
httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10;
|
httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10;
|
||||||
if (httpver == 10) {
|
if (httpver == 10) {
|
||||||
// HTTP 1.0 defaults to close, unless otherwise specified.
|
// HTTP 1.0 defaults to close, unless otherwise specified.
|
||||||
keepalive = strstr(p, "Connection: keep-alive") != NULL;
|
//keepalive = strstr(p, "Connection: keep-alive") != NULL;
|
||||||
} else if (httpver == 11) {
|
} else if (httpver == 11) {
|
||||||
// HTTP 1.1 defaults to keep-alive, unless close is specified.
|
// HTTP 1.1 defaults to keep-alive, unless close is specified.
|
||||||
keepalive = strstr(p, "Connection: close") == NULL;
|
//keepalive = strstr(p, "Connection: close") == NULL;
|
||||||
}
|
}
|
||||||
|
keepalive = 0;
|
||||||
|
|
||||||
// Identify he URL.
|
// Identify he URL.
|
||||||
p = strchr(p,' ');
|
p = strchr(p,' ');
|
||||||
|
|
@ -868,6 +900,10 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
nread = recv(c->fd, c->buf+c->buflen, left, 0);
|
nread = recv(c->fd, c->buf+c->buflen, left, 0);
|
||||||
if (nread < 0) {errno = WSAGetLastError();}
|
if (nread < 0) {errno = WSAGetLastError();}
|
||||||
#endif
|
#endif
|
||||||
|
if (nread == 0) {
|
||||||
|
modesCloseClient(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If we didn't get all the data we asked for, then return once we've processed what we did get.
|
// If we didn't get all the data we asked for, then return once we've processed what we did get.
|
||||||
if (nread != left) {
|
if (nread != left) {
|
||||||
|
|
@ -878,7 +914,7 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
#else
|
#else
|
||||||
if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file
|
if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file
|
||||||
#endif
|
#endif
|
||||||
modesFreeClient(c);
|
modesCloseClient(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nread <= 0) {
|
if (nread <= 0) {
|
||||||
|
|
@ -926,7 +962,7 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
}
|
}
|
||||||
// Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
|
// Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
|
||||||
if (handler(c, s)) {
|
if (handler(c, s)) {
|
||||||
modesFreeClient(c);
|
modesCloseClient(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fullmsg = 1;
|
fullmsg = 1;
|
||||||
|
|
@ -942,7 +978,7 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
while ((e = strstr(s, sep)) != NULL) { // end of first message if found
|
while ((e = strstr(s, sep)) != NULL) { // end of first message if found
|
||||||
*e = '\0'; // The handler expects null terminated strings
|
*e = '\0'; // The handler expects null terminated strings
|
||||||
if (handler(c, s)) { // Pass message to handler.
|
if (handler(c, s)) { // Pass message to handler.
|
||||||
modesFreeClient(c); // Handler returns 1 on error to signal we .
|
modesCloseClient(c); // Handler returns 1 on error to signal we .
|
||||||
return; // should close the client connection
|
return; // should close the client connection
|
||||||
}
|
}
|
||||||
s = e + strlen(sep); // Move to start of next message
|
s = e + strlen(sep); // Move to start of next message
|
||||||
|
|
@ -969,19 +1005,212 @@ void modesReadFromClients(void) {
|
||||||
struct client *c = modesAcceptClients();
|
struct client *c = modesAcceptClients();
|
||||||
|
|
||||||
while (c) {
|
while (c) {
|
||||||
// Read next before servicing client incase the service routine deletes the client!
|
// Read next before servicing client incase the service routine deletes the client!
|
||||||
struct client *next = c->next;
|
struct client *next = c->next;
|
||||||
|
|
||||||
if (c->service == Modes.ris) {
|
if (c->fd >= 0) {
|
||||||
modesReadFromClient(c,"\n",decodeHexMessage);
|
if (c->service == Modes.ris) {
|
||||||
} else if (c->service == Modes.bis) {
|
modesReadFromClient(c,"\n",decodeHexMessage);
|
||||||
modesReadFromClient(c,"",decodeBinMessage);
|
} else if (c->service == Modes.bis) {
|
||||||
} else if (c->service == Modes.https) {
|
modesReadFromClient(c,"",decodeBinMessage);
|
||||||
modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest);
|
} else if (c->service == Modes.https) {
|
||||||
|
modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modesFreeClient(c);
|
||||||
}
|
}
|
||||||
c = next;
|
c = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TSV_BUFFER_SIZE 8192
|
||||||
|
#define TSV_MAX_PACKET_SIZE 160
|
||||||
|
|
||||||
|
void showFlightsFATSV(void) {
|
||||||
|
struct aircraft *a = Modes.aircrafts;
|
||||||
|
time_t now = time(NULL), seen;
|
||||||
|
int age, emittedSecondsAgo;
|
||||||
|
static time_t lastTime = 0;
|
||||||
|
char msg[TSV_BUFFER_SIZE], *p = msg;
|
||||||
|
int nCombined = 0;
|
||||||
|
|
||||||
|
// don't do anything if there are no FA TSV connections
|
||||||
|
if (Modes.stat_fatsv_connections == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now - lastTime < 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(a = Modes.aircrafts; a; a = a->next) {
|
||||||
|
int altValid = 0;
|
||||||
|
int alt = 0;
|
||||||
|
int groundValid = 0;
|
||||||
|
int ground = 0;
|
||||||
|
int latlonValid = 0;
|
||||||
|
int useful = 0;
|
||||||
|
char *rollback = p;
|
||||||
|
|
||||||
|
if (0 && a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C
|
||||||
|
a = a->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ADSB messages have seenLatLon set, Mode A/C never set seenLatLon
|
||||||
|
if (a->seenLatLon == 0) {
|
||||||
|
seen = a->seen;
|
||||||
|
} else {
|
||||||
|
seen = a->seenLatLon;
|
||||||
|
}
|
||||||
|
age = (int)(seen - a->fatsv_last_emitted);
|
||||||
|
emittedSecondsAgo = (int)(seen - a->fatsv_last_emitted);
|
||||||
|
|
||||||
|
// don't emit if it hasn't updated since last time
|
||||||
|
if (age == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't emit more than once every five seconds
|
||||||
|
if (emittedSecondsAgo < 5) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) {
|
||||||
|
altValid = 1;
|
||||||
|
|
||||||
|
alt = a->altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_AOG_VALID) {
|
||||||
|
groundValid = 1;
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_AOG) {
|
||||||
|
alt = 0;
|
||||||
|
ground = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
|
||||||
|
latlonValid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's over 10,000 feet, don't emit more than once every 10 seconds
|
||||||
|
if (alt > 10000 && emittedSecondsAgo < 10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable if you want only ads-b
|
||||||
|
// also don't send mode S very often
|
||||||
|
if (!latlonValid) {
|
||||||
|
if (emittedSecondsAgo < 30) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if it hasn't changed altitude very much and it hasn't changed
|
||||||
|
// heading very much, don't update real often
|
||||||
|
if (abs(a->track - a->fatsv_emitted_track) < 2 && abs(alt - a->fatsv_emitted_altitude) < 50) {
|
||||||
|
if (alt < 10000) {
|
||||||
|
// it hasn't changed much but we're below 10,000 feet
|
||||||
|
// so update more frequently
|
||||||
|
if (emittedSecondsAgo < 10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// above 10,000 feet, don't update so often when it
|
||||||
|
// hasn't changed much
|
||||||
|
if (emittedSecondsAgo < 30) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, "clock\t%ld\thexid\t%06X", seen, a->addr);
|
||||||
|
|
||||||
|
// if ((a->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) && *a->flight != '\0') {
|
||||||
|
if (*a->flight != '\0') {
|
||||||
|
p += sprintf(p, "\tident\t%s", a->flight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_SQUAWK_VALID) {
|
||||||
|
p += sprintf(p, "\tsquawk\t%04x", a->modeA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (altValid) {
|
||||||
|
p += sprintf(p, "\talt\t%d", alt);
|
||||||
|
useful = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_SPEED_VALID) {
|
||||||
|
p += sprintf(p, "\tspeed\t%d", a->speed);
|
||||||
|
useful = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groundValid) {
|
||||||
|
if (ground) {
|
||||||
|
p += sprintf(p, "\tairGround\tG");
|
||||||
|
} else {
|
||||||
|
p += sprintf(p, "\tairGround\tA");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->lat != 0.0 || a->lon != 0.0) {
|
||||||
|
p += sprintf(p, "\tlat\t%.5f\tlon\t%.5f", a->lat, a->lon);
|
||||||
|
useful = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) {
|
||||||
|
p += sprintf(p, "\theading\t%d", a->track);
|
||||||
|
useful = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we didn't get at least an alt or a speed or a latlon or
|
||||||
|
// a heading, undo this message we've been prepping by setting
|
||||||
|
// the p pointer back to what it was when we started generating
|
||||||
|
// the message for this aircraft
|
||||||
|
if (!useful) {
|
||||||
|
p = rollback;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's a verbatim string and it's not null, append it to the
|
||||||
|
// message
|
||||||
|
if (a->tsvClient && a->tsvClient->tsvVerbatim && *a->tsvClient->tsvVerbatim != '\0') {
|
||||||
|
p += sprintf(p, "\t%s", a->tsvClient->tsvVerbatim);
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, "\n");
|
||||||
|
|
||||||
|
a->fatsv_last_emitted = seen;
|
||||||
|
a->fatsv_emitted_altitude = alt;
|
||||||
|
a->fatsv_emitted_track = a->track;
|
||||||
|
|
||||||
|
nCombined++;
|
||||||
|
|
||||||
|
// we are aggregating multiple messages into the buffer...
|
||||||
|
// if the buffer is getting pretty full, send what we've assembled
|
||||||
|
if (p - msg > TSV_BUFFER_SIZE - TSV_MAX_PACKET_SIZE) {
|
||||||
|
modesSendAllClients(Modes.fatsvos, msg, p-msg);
|
||||||
|
p = msg;
|
||||||
|
// printf("combined %d updates into one %ld-byte packet\n", nCombined, p-msg);
|
||||||
|
nCombined = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we've looked at all the candidate aircraft,
|
||||||
|
// if there's anything in the buffer, send it
|
||||||
|
if (p != msg) {
|
||||||
|
modesSendAllClients(Modes.fatsvos, msg, p-msg);
|
||||||
|
// printf("combined %d updates into one %ld-byte packet\n", nCombined, p-msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// =============================== Network IO ===========================
|
// =============================== Network IO ===========================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,7 @@ int main(int argc, char **argv) {
|
||||||
c->fd =
|
c->fd =
|
||||||
c->service =
|
c->service =
|
||||||
Modes.bis = fd;
|
Modes.bis = fd;
|
||||||
|
c->tsvVerbatim[0] = 0;
|
||||||
Modes.clients = c;
|
Modes.clients = c;
|
||||||
|
|
||||||
// Keep going till the user does something that stops us
|
// Keep going till the user does something that stops us
|
||||||
|
|
@ -259,3 +260,5 @@ int main(int argc, char **argv) {
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "rtl-sdr.h"
|
|
||||||
#include "anet.h"
|
#include "anet.h"
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#else
|
#else
|
||||||
|
|
@ -108,3 +107,5 @@ void postCOAA (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __PPUP1090_H
|
#endif // __PPUP1090_H
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ Metric = false; // true or false
|
||||||
CONST_CENTERLAT = 45.0;
|
CONST_CENTERLAT = 45.0;
|
||||||
CONST_CENTERLON = 9.0;
|
CONST_CENTERLON = 9.0;
|
||||||
// The google maps zoom level, 0 - 16, lower is further out
|
// The google maps zoom level, 0 - 16, lower is further out
|
||||||
CONST_ZOOMLVL = 5;
|
CONST_ZOOMLVL = 10;
|
||||||
|
|
||||||
// -- Marker settings -------------------------------------
|
// -- Marker settings -------------------------------------
|
||||||
// The default marker color
|
// The default marker color
|
||||||
MarkerColor = "rgb(127, 127, 127)";
|
MarkerColor = "rgb(127, 127, 127)";
|
||||||
|
MlatMarkerColor = "rgb(75, 75, 180)";
|
||||||
SelectedColor = "rgb(225, 225, 225)";
|
SelectedColor = "rgb(225, 225, 225)";
|
||||||
|
|
||||||
// -- Site Settings ---------------------------------------
|
// -- Site Settings ---------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
|
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css" />
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
|
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
|
||||||
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry"></script>
|
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry"></script>
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
<div id="map_container">
|
<div id="map_container">
|
||||||
<div id="map_canvas"></div>
|
<div id="map_canvas"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="grippie"></div>
|
||||||
<div id="sidebar_container">
|
<div id="sidebar_container">
|
||||||
<div id="sidebar_canvas">
|
<div id="sidebar_canvas">
|
||||||
<div id="timestamps" style="align: center">
|
<div id="timestamps" style="align: center">
|
||||||
|
|
@ -49,14 +50,29 @@
|
||||||
|
|
||||||
<div id="plane_detail"></div>
|
<div id="plane_detail"></div>
|
||||||
<div id="options"></div>
|
<div id="options"></div>
|
||||||
<div id="planes_table"></div>
|
<div id="planes_table">
|
||||||
|
<table id="tableinfo" width="100%">
|
||||||
|
<thead style="background-color: #BBBBBB; cursor: pointer;">
|
||||||
|
<td onclick="setASC_DESC('0');sortTable('tableinfo','0');">ICAO</td>
|
||||||
|
<td onclick="setASC_DESC('1');sortTable('tableinfo','1');">Flight</td>
|
||||||
|
<td onclick="setASC_DESC('2');sortTable('tableinfo','2');" align="right">Squawk</td>
|
||||||
|
<td onclick="setASC_DESC('3');sortTable('tableinfo','3');" align="right">Altitude</td>
|
||||||
|
<td onclick="setASC_DESC('4');sortTable('tableinfo','4');" align="right">Speed</td>
|
||||||
|
<td onclick="setASC_DESC('5');sortTable('tableinfo','5');" align="right">Track</td>
|
||||||
|
<td onclick="setASC_DESC('6');sortTable('tableinfo','6');" align="right">Msgs</td>
|
||||||
|
<td onclick="setASC_DESC('7');sortTable('tableinfo','7');" align="right">Seen</td>
|
||||||
|
</thead>
|
||||||
|
<tbody id="dataTable">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div id="plane_extension"></div>
|
<div id="plane_extension"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="SpecialSquawkWarning">
|
<div id="SpecialSquawkWarning">
|
||||||
<b>Squak 7x00 is reported and shown.</b><br>
|
<b>Squawk 7x00 is reported and shown.</b><br>
|
||||||
This is most likely an error in reciving or decoding.<br>
|
This is most likely an error in reciving or decoding.<br>
|
||||||
Please do not call the local authorities, they already know about it if it is valid squak.
|
Please do not call the local authorities, they already know about it if it is valid squawk.
|
||||||
</div>
|
</div>
|
||||||
<div id="container_splitter"></div>
|
<div id="container_splitter"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 742 B |
|
|
@ -23,6 +23,7 @@ var planeObject = {
|
||||||
// Vaild...
|
// Vaild...
|
||||||
vPosition : false,
|
vPosition : false,
|
||||||
vTrack : false,
|
vTrack : false,
|
||||||
|
mlat : false,
|
||||||
|
|
||||||
// GMap Details
|
// GMap Details
|
||||||
marker : null,
|
marker : null,
|
||||||
|
|
@ -53,6 +54,9 @@ var planeObject = {
|
||||||
|
|
||||||
// Should create an icon for us to use on the map...
|
// Should create an icon for us to use on the map...
|
||||||
funcGetIcon : function() {
|
funcGetIcon : function() {
|
||||||
|
if (this.mlat == true) {
|
||||||
|
this.markerColor = MlatMarkerColor;
|
||||||
|
}
|
||||||
// If this marker is selected we should make it lighter than the rest.
|
// If this marker is selected we should make it lighter than the rest.
|
||||||
if (this.is_selected == true) {
|
if (this.is_selected == true) {
|
||||||
this.markerColor = SelectedColor;
|
this.markerColor = SelectedColor;
|
||||||
|
|
@ -142,6 +146,7 @@ var planeObject = {
|
||||||
this.icao = data.hex;
|
this.icao = data.hex;
|
||||||
this.messages = data.messages;
|
this.messages = data.messages;
|
||||||
this.seen = data.seen;
|
this.seen = data.seen;
|
||||||
|
this.mlat = data.mlat;
|
||||||
|
|
||||||
// If no packet in over 58 seconds, consider the plane reapable
|
// If no packet in over 58 seconds, consider the plane reapable
|
||||||
// This way we can hold it, but not show it just in case the plane comes back
|
// This way we can hold it, but not show it just in case the plane comes back
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ var PlanesOnTable = 0;
|
||||||
var PlanesToReap = 0;
|
var PlanesToReap = 0;
|
||||||
var SelectedPlane = null;
|
var SelectedPlane = null;
|
||||||
var SpecialSquawk = false;
|
var SpecialSquawk = false;
|
||||||
|
var GotCenter = false;
|
||||||
|
|
||||||
var iSortCol=-1;
|
var iSortCol=-1;
|
||||||
var bSortASC=true;
|
var bSortASC=true;
|
||||||
|
|
@ -16,6 +17,7 @@ var iDefaultSortCol=3;
|
||||||
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
||||||
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
||||||
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
||||||
|
GotCenter = (CenterLat != CONST_CENTERLAT || CenterLon != CONST_CENTERLON);
|
||||||
|
|
||||||
function fetchData() {
|
function fetchData() {
|
||||||
$.getJSON('/dump1090/data.json', function(data) {
|
$.getJSON('/dump1090/data.json', function(data) {
|
||||||
|
|
@ -47,6 +49,13 @@ function fetchData() {
|
||||||
|
|
||||||
// Copy the plane into Planes
|
// Copy the plane into Planes
|
||||||
Planes[plane.icao] = plane;
|
Planes[plane.icao] = plane;
|
||||||
|
|
||||||
|
// Auto-center the map upon first valid position.
|
||||||
|
if (!GotCenter && data[j].validposition) {
|
||||||
|
var newpos = new google.maps.LatLng(data[j].lat, data[j].lon);
|
||||||
|
GoogleMap.panTo(newpos);
|
||||||
|
GotCenter = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlanesOnTable = data.length;
|
PlanesOnTable = data.length;
|
||||||
|
|
@ -267,8 +276,9 @@ function refreshSelected() {
|
||||||
} else if (selected && selected.squawk == 7700) { // General Emergency
|
} else if (selected && selected.squawk == 7700) { // General Emergency
|
||||||
html += ' <span class="squawk7700"> Squawking: General Emergency </span>';
|
html += ' <span class="squawk7700"> Squawking: General Emergency </span>';
|
||||||
} else if (selected && selected.flight != '') {
|
} else if (selected && selected.flight != '') {
|
||||||
html += ' <a href="http://www.flightstats.com/go/FlightStatus/flightStatusByFlight.do?';
|
// html += ' <a href="http://www.flightstats.com/go/FlightStatus/flightStatusByFlight.do?';
|
||||||
html += 'flightNumber='+selected.flight+'" target="_blank">[FlightStats]</a>';
|
// html += 'flightNumber='+selected.flight+'" target="_blank">[FlightStats]</a>';
|
||||||
|
html += ' <a href="http://flightaware.com/live/flight/'+selected.flight+'" target="_blank">[FlightAware]</a>';
|
||||||
}
|
}
|
||||||
html += '<td></tr>';
|
html += '<td></tr>';
|
||||||
|
|
||||||
|
|
@ -316,6 +326,9 @@ function refreshSelected() {
|
||||||
|
|
||||||
html += '<tr><td colspan="' + columns + '" align="center">Lat/Long: ';
|
html += '<tr><td colspan="' + columns + '" align="center">Lat/Long: ';
|
||||||
if (selected && selected.vPosition) {
|
if (selected && selected.vPosition) {
|
||||||
|
if (selected.mlat) {
|
||||||
|
html += "MLAT: ";
|
||||||
|
}
|
||||||
html += selected.latitude + ', ' + selected.longitude + '</td></tr>';
|
html += selected.latitude + ', ' + selected.longitude + '</td></tr>';
|
||||||
|
|
||||||
// Let's show some extra data if we have site coordinates
|
// Let's show some extra data if we have site coordinates
|
||||||
|
|
@ -393,22 +406,7 @@ function normalizeTrack(track, valid){
|
||||||
|
|
||||||
// Refeshes the larger table of all the planes
|
// Refeshes the larger table of all the planes
|
||||||
function refreshTableInfo() {
|
function refreshTableInfo() {
|
||||||
var html = '<table id="tableinfo" width="100%">';
|
var html = '';
|
||||||
html += '<thead style="background-color: #BBBBBB; cursor: pointer;">';
|
|
||||||
html += '<td onclick="setASC_DESC(\'0\');sortTable(\'tableinfo\',\'0\');">ICAO</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'1\');sortTable(\'tableinfo\',\'1\');">Flight</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'2\');sortTable(\'tableinfo\',\'2\');" ' +
|
|
||||||
'align="right">Squawk</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'3\');sortTable(\'tableinfo\',\'3\');" ' +
|
|
||||||
'align="right">Altitude</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'4\');sortTable(\'tableinfo\',\'4\');" ' +
|
|
||||||
'align="right">Speed</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'5\');sortTable(\'tableinfo\',\'5\');" ' +
|
|
||||||
'align="right">Track</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'6\');sortTable(\'tableinfo\',\'6\');" ' +
|
|
||||||
'align="right">Msgs</td>';
|
|
||||||
html += '<td onclick="setASC_DESC(\'7\');sortTable(\'tableinfo\',\'7\');" ' +
|
|
||||||
'align="right">Seen</td></thead><tbody>';
|
|
||||||
for (var tablep in Planes) {
|
for (var tablep in Planes) {
|
||||||
var tableplane = Planes[tablep]
|
var tableplane = Planes[tablep]
|
||||||
if (!tableplane.reapable) {
|
if (!tableplane.reapable) {
|
||||||
|
|
@ -431,9 +429,13 @@ function refreshTableInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tableplane.vPosition == true) {
|
if (tableplane.vPosition == true) {
|
||||||
html += '<tr class="plane_table_row vPosition' + specialStyle + '">';
|
if (tableplane.mlat == true) {
|
||||||
|
html += '<tr onclick="planeTRclick(\''+tableplane.icao+'\')" class="plane_table_row mlat' + specialStyle + '">';
|
||||||
|
} else {
|
||||||
|
html += '<tr onclick="planeTRclick(\''+tableplane.icao+'\')" class="plane_table_row vPosition' + specialStyle + '">';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
html += '<tr class="plane_table_row ' + specialStyle + '">';
|
html += '<tr onclick="planeTRclick(\''+tableplane.icao+'\')" class="plane_table_row ' + specialStyle + '">';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<td>' + tableplane.icao + '</td>';
|
html += '<td>' + tableplane.icao + '</td>';
|
||||||
|
|
@ -465,9 +467,8 @@ function refreshTableInfo() {
|
||||||
html += '</tr>';
|
html += '</tr>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html += '</tbody></table>';
|
|
||||||
|
|
||||||
document.getElementById('planes_table').innerHTML = html;
|
document.getElementById('dataTable').innerHTML = html;
|
||||||
|
|
||||||
if (SpecialSquawk) {
|
if (SpecialSquawk) {
|
||||||
$('#SpecialSquawkWarning').css('display', 'inline');
|
$('#SpecialSquawkWarning').css('display', 'inline');
|
||||||
|
|
@ -475,16 +476,6 @@ function refreshTableInfo() {
|
||||||
$('#SpecialSquawkWarning').css('display', 'none');
|
$('#SpecialSquawkWarning').css('display', 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Click event for table
|
|
||||||
$('#planes_table').find('tr').click( function(){
|
|
||||||
var hex = $(this).find('td:first').text();
|
|
||||||
if (hex != "ICAO") {
|
|
||||||
selectPlaneByHex(hex);
|
|
||||||
refreshTableInfo();
|
|
||||||
refreshSelected();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sortTable("tableinfo");
|
sortTable("tableinfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -591,6 +582,7 @@ function resetMap() {
|
||||||
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
|
||||||
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON;
|
||||||
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL;
|
||||||
|
GotCenter = false;
|
||||||
|
|
||||||
// Set and refresh
|
// Set and refresh
|
||||||
GoogleMap.setZoom(parseInt(ZoomLvl));
|
GoogleMap.setZoom(parseInt(ZoomLvl));
|
||||||
|
|
@ -628,3 +620,21 @@ function drawCircle(marker, distance) {
|
||||||
});
|
});
|
||||||
circle.bindTo('center', marker, 'position');
|
circle.bindTo('center', marker, 'position');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function planeTRclick(hex) {
|
||||||
|
selectPlaneByHex(hex);
|
||||||
|
refreshTableInfo();
|
||||||
|
refreshSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind grippie actions
|
||||||
|
$(function() {
|
||||||
|
var handleClick = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$("#sidebar_container").toggle();
|
||||||
|
$("#map_canvas, #grippie").toggleClass("fullscreen");
|
||||||
|
google.maps.event.trigger(GoogleMap, "resize");
|
||||||
|
};
|
||||||
|
|
||||||
|
$("#grippie").click(handleClick);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,15 @@ html, body {
|
||||||
div#map_container { float: left; width: 100%; height: 100%; }
|
div#map_container { float: left; width: 100%; height: 100%; }
|
||||||
div#map_canvas { height: 100%; margin-right: 420px; }
|
div#map_canvas { height: 100%; margin-right: 420px; }
|
||||||
|
|
||||||
div#sidebar_container { float: left; width: 410px; margin-left: -410px; height: 100%; overflow: auto; }
|
div#sidebar_container { float: left; width: 400px; margin-left: -400px; height: 100%; overflow: auto; }
|
||||||
|
|
||||||
|
div#grippie { border: 1px solid #ddd; border-width: 0 1px 1px; cursor: e-resize; width: 9px;
|
||||||
|
overflow: hidden; background-color: #eee; background-image: url('grippie.png');
|
||||||
|
background-repeat: no-repeat; background-position: 50% 50%;
|
||||||
|
float: left; margin-left: -420px; height: 100%; }
|
||||||
|
|
||||||
|
div#grippie.fullscreen { float: right; cursor: w-resize; }
|
||||||
|
div#map_canvas.fullscreen { margin-right: 11px; }
|
||||||
|
|
||||||
div#SpecialSquawkWarning { position: absolute; bottom: 25px; right: 430px; border: 2px solid red;
|
div#SpecialSquawkWarning { position: absolute; bottom: 25px; right: 430px; border: 2px solid red;
|
||||||
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
background-color: #FFFFA3; opacity: 0.75; filter:alpha(opacity=75); padding: 5px;
|
||||||
|
|
@ -17,6 +25,7 @@ table#optionsTabs { width: 100%; font-size: small; font-family: monospace; backg
|
||||||
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
|
#tableinfo, #sudo_buttons { font-size: x-small; font-family: monospace; }
|
||||||
|
|
||||||
.vPosition { font-weight: bold; background-color: #d5ffd5; }
|
.vPosition { font-weight: bold; background-color: #d5ffd5; }
|
||||||
|
.mlat { font-weight: bold; background-color: #d5d5ff; }
|
||||||
.squawk7500 { font-weight: bold; background-color: #ff5555; }
|
.squawk7500 { font-weight: bold; background-color: #ff5555; }
|
||||||
.squawk7600 { font-weight: bold; background-color: #00ffff; }
|
.squawk7600 { font-weight: bold; background-color: #00ffff; }
|
||||||
.squawk7700 { font-weight: bold; background-color: #ffff00; }
|
.squawk7700 { font-weight: bold; background-color: #ffff00; }
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,7 @@ int setupConnection(struct client *c) {
|
||||||
c->fd =
|
c->fd =
|
||||||
c->service =
|
c->service =
|
||||||
Modes.bis = fd;
|
Modes.bis = fd;
|
||||||
|
c->tsvVerbatim[0] = 0;
|
||||||
Modes.clients = c;
|
Modes.clients = c;
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
|
@ -319,3 +320,5 @@ int main(int argc, char **argv) {
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include "rtl-sdr.h"
|
|
||||||
#include "anet.h"
|
#include "anet.h"
|
||||||
#else
|
#else
|
||||||
#include "winstubs.h" //Put everything Windows specific in here
|
#include "winstubs.h" //Put everything Windows specific in here
|
||||||
|
|
@ -82,3 +81,5 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __VIEW1090_H
|
#endif // __VIEW1090_H
|
||||||
|
|
||||||
|
// vim: set ts=4 sw=4 sts=4 expandtab :
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue