Merge branch 'dev' into build-instructions
This commit is contained in:
commit
f573b843c3
|
@ -16,7 +16,7 @@ matrix:
|
|||
before_install:
|
||||
- if [ `uname` = "Linux" ]; then
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -y build-essential debhelper librtlsdr-dev libusb-1.0-0-dev pkg-config;
|
||||
sudo apt-get install -y build-essential debhelper librtlsdr-dev libusb-1.0-0-dev pkg-config fakeroot libbladerf-dev dh-systemd;
|
||||
elif [ `uname` = "Darwin" ]; then
|
||||
brew update;
|
||||
brew install -v librtlsdr;
|
||||
|
|
20
Makefile
20
Makefile
|
@ -15,16 +15,20 @@ ifeq ($(RTLSDR), yes)
|
|||
|
||||
ifdef RTLSDR_PREFIX
|
||||
CPPFLAGS += -I$(RTLSDR_PREFIX)/include
|
||||
LDFLAGS += -L$(RTLSDR_PREFIX)/lib
|
||||
ifeq ($(STATIC), yes)
|
||||
LIBS_SDR += -L$(RTLSDR_PREFIX)/lib -Wl,-Bstatic -lrtlsdr -Wl,-Bdynamic -lusb-1.0
|
||||
else
|
||||
LIBS_SDR += -L$(RTLSDR_PREFIX)/lib -lrtlsdr -lusb-1.0
|
||||
endif
|
||||
else
|
||||
CFLAGS += $(shell pkg-config --cflags librtlsdr)
|
||||
LDFLAGS += $(shell pkg-config --libs-only-L librtlsdr)
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC), yes)
|
||||
LIBS_SDR += -Wl,-Bstatic -lrtlsdr -Wl,-Bdynamic -lusb-1.0
|
||||
else
|
||||
LIBS_SDR += -lrtlsdr -lusb-1.0
|
||||
# some packaged .pc files are massively broken, try to handle it
|
||||
RTLSDR_LFLAGS := $(shell pkg-config --libs-only-L librtlsdr)
|
||||
ifeq ($(RTLSDR_LFLAGS),-L)
|
||||
LIBS_SDR += $(shell pkg-config --libs-only-l --libs-only-other librtlsdr)
|
||||
else
|
||||
LIBS_SDR += $(shell pkg-config --libs librtlsdr)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
12
README.md
12
README.md
|
@ -6,6 +6,14 @@ customized for use within [FlightAware](http://flightaware.com)'s
|
|||
|
||||
It is designed to build as a Debian package.
|
||||
|
||||
## Building under stretch
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install build-essential debhelper librtlsdr-dev pkg-config dh-systemd libncurses5-dev libbladerf-dev
|
||||
$ dpkg-buildpackage -b
|
||||
```
|
||||
|
||||
|
||||
## Building under jessie
|
||||
|
||||
### Dependencies - bladeRF
|
||||
|
@ -44,8 +52,8 @@ You can probably just run "make" after installing the required dependencies.
|
|||
Binaries are built in the source directory; you will need to arrange to
|
||||
install them (and a method for starting them) yourself.
|
||||
|
||||
"make BLADERF=no" will disable bladeRF support and remove the dependency on
|
||||
``make BLADERF=no`` will disable bladeRF support and remove the dependency on
|
||||
libbladeRF.
|
||||
|
||||
"make RTLSDR=no" will disable rtl-sdr support and remove the dependency on
|
||||
``make RTLSDR=no`` will disable rtl-sdr support and remove the dependency on
|
||||
librtlsdr.
|
||||
|
|
34
debian/changelog
vendored
34
debian/changelog
vendored
|
@ -1,3 +1,37 @@
|
|||
dump1090-fa (3.7.1~dev) UNRELEASED; urgency=medium
|
||||
|
||||
* in development
|
||||
|
||||
-- Eric Tran <eric.tran@flightaware.com> Mon, 15 Apr 2019 11:23:00 -6000
|
||||
|
||||
dump1090-fa (3.7.0.1) stable; urgency=medium
|
||||
|
||||
* dump1090: Fix piaware lat/lon variable
|
||||
|
||||
-- Eric Tran <eric.tran@flightaware.com> Fri, 29 Mar 2019 7:04:00 -6000
|
||||
|
||||
dump1090-fa (3.7.0) stable; urgency=medium
|
||||
|
||||
* dump1090: Fix Rc decoding errors
|
||||
* dump1090: Compute ADS-B v0 NACp/SIL
|
||||
* dump1090: When generating aircraft.json, leave space for the final line;
|
||||
otherwise the generated json may have trailing garbage
|
||||
* dump1090: Don't update the known-address-set from DF18 messages
|
||||
* Skyview: use heading data for icon orientation if track data is unavailable
|
||||
* Skyview: don't spin forever if there's no history to load / receiver.json
|
||||
is missing
|
||||
* dump1090: Bail out if rtlsdr_read_async() returns early; it probably means we lost
|
||||
the USB device. There was a workaround for this (originally implemented
|
||||
in dump1090-mutability) that got lost in the refactoring needed to support
|
||||
different SDRs. librtlsdr can still be flaky under disconnect conditions, so
|
||||
this won't catch everything.
|
||||
* dump1090: add ENABLED to /etc/default/dump1090-fa
|
||||
* dump1090: track FMS and MCP selected altitudes separately
|
||||
* skyview: use whichever selected altitude is available
|
||||
* faup1090: updates to support PiAware 3.7.0
|
||||
|
||||
-- Oliver Jowett <oliver@mutability.co.uk> Fri, 22 Mar 2019 15:58:04 +0000
|
||||
|
||||
dump1090-fa (3.6.3) stable; urgency=medium
|
||||
|
||||
* Fix port 30003 output (Basestation) timestamp formatting broken in 3.6.0
|
||||
|
|
7
debian/dump1090-fa.default
vendored
7
debian/dump1090-fa.default
vendored
|
@ -1,11 +1,14 @@
|
|||
# dump1090-fa configuration
|
||||
# This is read by the systemd service file as an environment file,
|
||||
# and evaluated by some scripts as a POSIX shell fragment.
|
||||
# This is sourced by /usr/share/dump1090-fa/start-dump1090-fa as a
|
||||
# shellscript fragment.
|
||||
|
||||
# If you are using a PiAware sdcard image, this config file is regenerated
|
||||
# on boot based on the contents of piaware-config.txt; any changes made to this
|
||||
# file will be lost.
|
||||
|
||||
# dump1090-fa won't automatically start unless ENABLED=yes
|
||||
ENABLED=yes
|
||||
|
||||
RECEIVER_OPTIONS="--device-index 0 --gain -10 --ppm 0 --net-bo-port 30005"
|
||||
DECODER_OPTIONS="--max-range 360"
|
||||
NET_OPTIONS="--net --net-heartbeat 60 --net-ro-size 1000 --net-ro-interval 1 --net-ri-port 0 --net-ro-port 30002 --net-sbs-port 30003 --net-bi-port 30004,30104 --net-bo-port 30005"
|
||||
|
|
3
debian/dump1090-fa.install
vendored
3
debian/dump1090-fa.install
vendored
|
@ -1,3 +1,4 @@
|
|||
public_html/* usr/share/dump1090-fa/html
|
||||
debian/lighttpd/* etc/lighttpd/conf-available
|
||||
bladerf/* /usr/share/dump1090-fa/bladerf
|
||||
bladerf/* usr/share/dump1090-fa/bladerf
|
||||
debian/start-dump1090-fa usr/share/dump1090-fa/
|
||||
|
|
14
debian/dump1090-fa.postinst
vendored
14
debian/dump1090-fa.postinst
vendored
|
@ -49,6 +49,20 @@ case "$1" in
|
|||
fi
|
||||
fi
|
||||
|
||||
# on upgrade, add an ENABLED line if it's not already present
|
||||
if dpkg --compare-versions "$2" lt-nl "3.7.0"
|
||||
then
|
||||
if [ -f /etc/default/dump1090-fa ]
|
||||
then
|
||||
if ! grep -q -E '^ENABLED=' /etc/default/dump1090-fa
|
||||
then
|
||||
echo "Setting ENABLED=yes in /etc/default/dump1090-fa.." >&2
|
||||
echo "# Automatically added by upgrade from $2" >>/etc/default/dump1090-fa
|
||||
echo "ENABLED=yes" >>/etc/default/dump1090-fa
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Restarting lighttpd.." >&2
|
||||
invoke-rc.d lighttpd restart || true
|
||||
;;
|
||||
|
|
8
debian/dump1090-fa.service
vendored
8
debian/dump1090-fa.service
vendored
|
@ -7,17 +7,15 @@ Wants=network.target
|
|||
After=network.target
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/etc/default/dump1090-fa
|
||||
EnvironmentFile=-/var/cache/piaware/location.env
|
||||
User=dump1090
|
||||
RuntimeDirectory=dump1090-fa
|
||||
RuntimeDirectoryMode=0755
|
||||
ExecStart=/usr/bin/dump1090-fa \
|
||||
$RECEIVER_OPTIONS $DECODER_OPTIONS $NET_OPTIONS $JSON_OPTIONS $PIAWARE_DUMP1090_LOCATION_OPTIONS \
|
||||
--write-json /run/dump1090-fa --quiet
|
||||
ExecStart=/usr/share/dump1090-fa/start-dump1090-fa --write-json %t/dump1090-fa --quiet
|
||||
SyslogIdentifier=dump1090-fa
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=30
|
||||
RestartPreventExitStatus=64
|
||||
Nice=-5
|
||||
|
||||
[Install]
|
||||
|
|
33
debian/start-dump1090-fa
vendored
Executable file
33
debian/start-dump1090-fa
vendored
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Helper script that reads /etc/default/dump1090-fa
|
||||
# and either starts dump1090-fa with the configured
|
||||
# arguments, or exits with status 64 to tell systemd
|
||||
# not to auto-restart the service.
|
||||
|
||||
if [ -f /etc/default/dump1090-fa ]
|
||||
then
|
||||
. /etc/default/dump1090-fa
|
||||
fi
|
||||
|
||||
if [ -f /var/cache/piaware/location.env ]
|
||||
then
|
||||
. /var/cache/piaware/location.env
|
||||
fi
|
||||
|
||||
if [ "x$ENABLED" != "xyes" ]
|
||||
then
|
||||
echo "dump1090-fa not enabled in /etc/default/dump1090-fa" >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
if [ -n "$PIAWARE_LAT" -a -n "$PIAWARE_LON" ]
|
||||
then
|
||||
POSITION="--lat $PIAWARE_LAT --lon $PIAWARE_LON"
|
||||
fi
|
||||
|
||||
exec /usr/bin/dump1090-fa \
|
||||
$RECEIVER_OPTIONS $DECODER_OPTIONS $NET_OPTIONS $JSON_OPTIONS $POSITION \
|
||||
"$@"
|
||||
# exec failed, do not restart
|
||||
exit 64
|
21
dump1090.c
21
dump1090.c
|
@ -224,15 +224,12 @@ void *readerThreadEntryPoint(void *arg)
|
|||
|
||||
// Wake the main thread (if it's still waiting)
|
||||
pthread_mutex_lock(&Modes.data_mutex);
|
||||
Modes.exit = 1; // just in case
|
||||
if (!Modes.exit)
|
||||
Modes.exit = 2; // unexpected exit
|
||||
pthread_cond_signal(&Modes.data_cond);
|
||||
pthread_mutex_unlock(&Modes.data_mutex);
|
||||
|
||||
#ifndef _WIN32
|
||||
pthread_exit(NULL);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
//
|
||||
// ============================== Snip mode =================================
|
||||
|
@ -760,15 +757,15 @@ int main(int argc, char **argv) {
|
|||
display_total_stats();
|
||||
}
|
||||
|
||||
log_with_timestamp("Normal exit.");
|
||||
|
||||
sdrClose();
|
||||
|
||||
#ifndef _WIN32
|
||||
pthread_exit(0);
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
if (Modes.exit == 1) {
|
||||
log_with_timestamp("Normal exit.");
|
||||
return 0;
|
||||
} else {
|
||||
log_with_timestamp("Abnormal exit.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//
|
||||
//=========================================================================
|
||||
|
|
|
@ -227,6 +227,10 @@ typedef enum {
|
|||
EMERGENCY_RESERVED = 7
|
||||
} emergency_t;
|
||||
|
||||
typedef enum {
|
||||
NAV_ALT_INVALID, NAV_ALT_UNKNOWN, NAV_ALT_AIRCRAFT, NAV_ALT_MCP, NAV_ALT_FMS
|
||||
} nav_altitude_source_t;
|
||||
|
||||
#define MODES_NON_ICAO_ADDRESS (1<<24) // Set on addresses to indicate they are not ICAO addresses
|
||||
|
||||
#define MODES_DEBUG_DEMOD (1<<0)
|
||||
|
@ -304,7 +308,7 @@ struct { // Internal state
|
|||
double sample_rate; // actual sample rate in use (in hz)
|
||||
|
||||
uint16_t *log10lut; // Magnitude -> log10 lookup table
|
||||
int exit; // Exit from the main loop when true
|
||||
int exit; // Exit from the main loop when true (2 = unclean exit)
|
||||
|
||||
// Sample conversion
|
||||
int dc_filter; // should we apply a DC filter?
|
||||
|
@ -581,7 +585,7 @@ struct modesMessage {
|
|||
unsigned mcp_altitude; // MCP/FCU selected altitude
|
||||
float qnh; // altimeter setting (QFE or QNH/QNE), millibars
|
||||
|
||||
enum { NAV_ALT_INVALID, NAV_ALT_UNKNOWN, NAV_ALT_AIRCRAFT, NAV_ALT_MCP, NAV_ALT_FMS } altitude_source;
|
||||
nav_altitude_source_t altitude_source;
|
||||
|
||||
nav_modes_t modes;
|
||||
} nav;
|
||||
|
|
|
@ -204,7 +204,6 @@ int main(int argc, char **argv) {
|
|||
// Set up output connection on stdout
|
||||
fatsv_output = makeFatsvOutputService();
|
||||
createGenericClient(fatsv_output, STDOUT_FILENO);
|
||||
writeFATSVHeader();
|
||||
|
||||
// Run it until we've lost either connection
|
||||
while (!Modes.exit && beast_input->connections && fatsv_output->connections) {
|
||||
|
|
10
mode_s.c
10
mode_s.c
|
@ -568,9 +568,9 @@ int decodeModesMessage(struct modesMessage *mm, unsigned char *msg)
|
|||
mm->CC = getbit(msg, 7);
|
||||
}
|
||||
|
||||
// CF (Control field)
|
||||
// CF (Control field, see Figure 2-2 ADS-B Message BaselineFormat Structure)
|
||||
if (mm->msgtype == 18) {
|
||||
mm->CF = getbits(msg, 5, 8);
|
||||
mm->CF = getbits(msg, 6, 8);
|
||||
}
|
||||
|
||||
// DR (Downlink Request)
|
||||
|
@ -1053,7 +1053,7 @@ static void decodeESTargetStatus(struct modesMessage *mm, int check_imf)
|
|||
// nothing
|
||||
break;
|
||||
}
|
||||
// 10: target altitude type (ignored)
|
||||
// 10: target altitude type (MSL or Baro, ignored)
|
||||
// 11: backward compatibility bit, always 0
|
||||
// 12-13: target alt capabilities (ignored)
|
||||
// 14-15: vertical mode
|
||||
|
@ -1081,7 +1081,7 @@ static void decodeESTargetStatus(struct modesMessage *mm, int check_imf)
|
|||
break;
|
||||
}
|
||||
|
||||
// 16-25: altitude
|
||||
// 16-25: target altitude
|
||||
int alt = -1000 + 100 * getbits(me, 16, 25);
|
||||
switch (mm->nav.altitude_source) {
|
||||
case NAV_ALT_MCP:
|
||||
|
@ -1109,7 +1109,7 @@ static void decodeESTargetStatus(struct modesMessage *mm, int check_imf)
|
|||
mm->nav.heading_type = HEADING_MAGNETIC_OR_TRUE;
|
||||
}
|
||||
}
|
||||
// 38-39: horiontal mode
|
||||
// 38-39: horizontal mode
|
||||
switch (getbits(me, 38, 39)) {
|
||||
case 1: // acquiring
|
||||
case 2: // maintaining
|
||||
|
|
72
net_io.c
72
net_io.c
|
@ -1155,8 +1155,10 @@ static char *append_flags(char *p, char *end, struct aircraft *a, datasource_t s
|
|||
p = safe_snprintf(p, end, "\"emergency\",");
|
||||
if (a->nav_qnh_valid.source == source)
|
||||
p = safe_snprintf(p, end, "\"nav_qnh\",");
|
||||
if (a->nav_altitude_valid.source == source)
|
||||
p = safe_snprintf(p, end, "\"nav_altitude\",");
|
||||
if (a->nav_altitude_mcp_valid.source == source)
|
||||
p = safe_snprintf(p, end, "\"nav_altitude_mcp\",");
|
||||
if (a->nav_altitude_fms_valid.source == source)
|
||||
p = safe_snprintf(p, end, "\"nav_altitude_fms\",");
|
||||
if (a->nav_heading_valid.source == source)
|
||||
p = safe_snprintf(p, end, "\"nav_heading\",");
|
||||
if (a->nav_modes_valid.source == source)
|
||||
|
@ -1267,6 +1269,18 @@ static const char *sil_type_enum_string(sil_type_t type)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *nav_altitude_source_enum_string(nav_altitude_source_t src)
|
||||
{
|
||||
switch (src) {
|
||||
case NAV_ALT_INVALID: return "invalid";
|
||||
case NAV_ALT_UNKNOWN: return "unknown";
|
||||
case NAV_ALT_AIRCRAFT: return "aircraft";
|
||||
case NAV_ALT_MCP: return "mcp";
|
||||
case NAV_ALT_FMS: return "fms";
|
||||
default: return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
char *generateAircraftJson(const char *url_path, int *len) {
|
||||
uint64_t now = mstime();
|
||||
struct aircraft *a;
|
||||
|
@ -1341,8 +1355,10 @@ char *generateAircraftJson(const char *url_path, int *len) {
|
|||
p = safe_snprintf(p, end, ",\"category\":\"%02X\"", a->category);
|
||||
if (trackDataValid(&a->nav_qnh_valid))
|
||||
p = safe_snprintf(p, end, ",\"nav_qnh\":%.1f", a->nav_qnh);
|
||||
if (trackDataValid(&a->nav_altitude_valid))
|
||||
p = safe_snprintf(p, end, ",\"nav_altitude\":%d", a->nav_altitude);
|
||||
if (trackDataValid(&a->nav_altitude_mcp_valid))
|
||||
p = safe_snprintf(p, end, ",\"nav_altitude_mcp\":%d", a->nav_altitude_mcp);
|
||||
if (trackDataValid(&a->nav_altitude_fms_valid))
|
||||
p = safe_snprintf(p, end, ",\"nav_altitude_fms\":%d", a->nav_altitude_fms);
|
||||
if (trackDataValid(&a->nav_heading_valid))
|
||||
p = safe_snprintf(p, end, ",\"nav_heading\":%.1f", a->nav_heading);
|
||||
if (trackDataValid(&a->nav_modes_valid)) {
|
||||
|
@ -1534,7 +1550,7 @@ char *generateStatsJson(const char *url_path, int *len) {
|
|||
p = appendStatsJson(p, end, &add, "total");
|
||||
p = safe_snprintf(p, end, "\n}\n");
|
||||
|
||||
assert(p <= end);
|
||||
assert(p < end);
|
||||
|
||||
*len = p-buf;
|
||||
return buf;
|
||||
|
@ -1862,27 +1878,8 @@ __attribute__ ((format (printf,4,5))) static char *appendFATSV(char *p, char *en
|
|||
return p;
|
||||
}
|
||||
|
||||
#define TSV_MAX_PACKET_SIZE 600
|
||||
#define TSV_VERSION 3
|
||||
|
||||
void writeFATSVHeader()
|
||||
{
|
||||
char *p = prepareWrite(&Modes.fatsv_out, TSV_MAX_PACKET_SIZE);
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
char *end = p + TSV_MAX_PACKET_SIZE;
|
||||
|
||||
p = appendFATSV(p, end, "clock", "%" PRIu64, mstime() / 1000);
|
||||
p = appendFATSV(p, end, "tsv_version", "%u", TSV_VERSION);
|
||||
--p; // remove last tab
|
||||
p = safe_snprintf(p, end, "\n");
|
||||
|
||||
if (p <= end)
|
||||
completeWrite(&Modes.fatsv_out, p);
|
||||
else
|
||||
fprintf(stderr, "fatsv: output too large (max %d, overran by %d)\n", TSV_MAX_PACKET_SIZE, (int) (p - end));
|
||||
}
|
||||
#define TSV_MAX_PACKET_SIZE 800
|
||||
#define TSV_VERSION "4E"
|
||||
|
||||
static void writeFATSVPositionUpdate(float lat, float lon, float alt)
|
||||
{
|
||||
|
@ -1901,6 +1898,7 @@ static void writeFATSVPositionUpdate(float lat, float lon, float alt)
|
|||
|
||||
char *end = p + TSV_MAX_PACKET_SIZE;
|
||||
|
||||
p = appendFATSV(p, end, "_v", "%s", TSV_VERSION);
|
||||
p = appendFATSV(p, end, "clock", "%" PRIu64, messageNow() / 1000);
|
||||
p = appendFATSV(p, end, "type", "%s", "location_update");
|
||||
p = appendFATSV(p, end, "lat", "%.5f", lat);
|
||||
|
@ -1910,7 +1908,7 @@ static void writeFATSVPositionUpdate(float lat, float lon, float alt)
|
|||
--p; // remove last tab
|
||||
p = safe_snprintf(p, end, "\n");
|
||||
|
||||
if (p <= end)
|
||||
if (p < end)
|
||||
completeWrite(&Modes.fatsv_out, p);
|
||||
else
|
||||
fprintf(stderr, "fatsv: output too large (max %d, overran by %d)\n", TSV_MAX_PACKET_SIZE, (int) (p - end));
|
||||
|
@ -1924,6 +1922,7 @@ static void writeFATSVEventMessage(struct modesMessage *mm, const char *datafiel
|
|||
|
||||
char *end = p + TSV_MAX_PACKET_SIZE;
|
||||
|
||||
p = appendFATSV(p, end, "_v", "%s", TSV_VERSION);
|
||||
p = appendFATSV(p, end, "clock", "%" PRIu64, messageNow() / 1000);
|
||||
p = appendFATSV(p, end, (mm->addr & MODES_NON_ICAO_ADDRESS) ? "otherid" : "hexid", "%06X", mm->addr & 0xFFFFFF);
|
||||
if (mm->addrtype != ADDR_ADSB_ICAO) {
|
||||
|
@ -1936,7 +1935,7 @@ static void writeFATSVEventMessage(struct modesMessage *mm, const char *datafiel
|
|||
}
|
||||
p = safe_snprintf(p, end, "\n");
|
||||
|
||||
if (p <= end)
|
||||
if (p < end)
|
||||
completeWrite(&Modes.fatsv_out, p);
|
||||
else
|
||||
fprintf(stderr, "fatsv: output too large (max %d, overran by %d)\n", TSV_MAX_PACKET_SIZE, (int) (p - end));
|
||||
|
@ -2136,7 +2135,9 @@ static void writeFATSV()
|
|||
(trackDataValid(&a->mach_valid) && fabs(a->mach - a->fatsv_emitted_mach) >= 0.02);
|
||||
|
||||
int immediate =
|
||||
(trackDataValid(&a->nav_altitude_valid) && unsigned_difference(a->nav_altitude, a->fatsv_emitted_nav_altitude) > 50) ||
|
||||
(trackDataValid(&a->nav_altitude_mcp_valid) && unsigned_difference(a->nav_altitude_mcp, a->fatsv_emitted_nav_altitude_mcp) > 50) ||
|
||||
(trackDataValid(&a->nav_altitude_fms_valid) && unsigned_difference(a->nav_altitude_fms, a->fatsv_emitted_nav_altitude_fms) > 50) ||
|
||||
(trackDataValid(&a->nav_altitude_src_valid) && a->nav_altitude_src != a->fatsv_emitted_nav_altitude_src) ||
|
||||
(trackDataValid(&a->nav_heading_valid) && heading_difference(a->nav_heading, a->fatsv_emitted_nav_heading) > 2) ||
|
||||
(trackDataValid(&a->nav_modes_valid) && a->nav_modes != a->fatsv_emitted_nav_modes) ||
|
||||
(trackDataValid(&a->nav_qnh_valid) && fabs(a->nav_qnh - a->fatsv_emitted_nav_qnh) > 0.8) || // 0.8 is the ES message resolution
|
||||
|
@ -2174,6 +2175,7 @@ static void writeFATSV()
|
|||
return;
|
||||
char *end = p + TSV_MAX_PACKET_SIZE;
|
||||
|
||||
p = appendFATSV(p, end, "_v", "%s", TSV_VERSION);
|
||||
p = appendFATSV(p, end, "clock", "%" PRIu64, messageNow() / 1000);
|
||||
p = appendFATSV(p, end, (a->addr & MODES_NON_ICAO_ADDRESS) ? "otherid" : "hexid", "%06X", a->addr & 0xFFFFFF);
|
||||
|
||||
|
@ -2236,8 +2238,10 @@ static void writeFATSV()
|
|||
p = appendFATSVMeta(p, end, "track_rate", a, &a->track_rate_valid, "%.2f", a->track_rate);
|
||||
p = appendFATSVMeta(p, end, "roll", a, &a->roll_valid, "%.1f", a->roll);
|
||||
p = appendFATSVMeta(p, end, "heading_magnetic", a, &a->mag_heading_valid, "%.1f", a->mag_heading);
|
||||
p = appendFATSVMeta(p, end, "heading_true", a, &a->true_heading_valid, "%.1f", a->true_heading);
|
||||
p = appendFATSVMeta(p, end, "nav_alt", a, &a->nav_altitude_valid, "%u", a->nav_altitude);
|
||||
p = appendFATSVMeta(p, end, "heading_true", a, &a->true_heading_valid, "%.1f", a->true_heading);
|
||||
p = appendFATSVMeta(p, end, "nav_alt_mcp", a, &a->nav_altitude_mcp_valid, "%u", a->nav_altitude_mcp);
|
||||
p = appendFATSVMeta(p, end, "nav_alt_fms", a, &a->nav_altitude_fms_valid, "%u", a->nav_altitude_fms);
|
||||
p = appendFATSVMeta(p, end, "nav_alt_src", a, &a->nav_altitude_src_valid, "%s", nav_altitude_source_enum_string(a->nav_altitude_src));
|
||||
p = appendFATSVMeta(p, end, "nav_heading", a, &a->nav_heading_valid, "%.1f", a->nav_heading);
|
||||
p = appendFATSVMeta(p, end, "nav_modes", a, &a->nav_modes_valid, "{%s}", nav_modes_flags_string(a->nav_modes));
|
||||
p = appendFATSVMeta(p, end, "nav_qnh", a, &a->nav_qnh_valid, "%.1f", a->nav_qnh);
|
||||
|
@ -2252,7 +2256,7 @@ static void writeFATSV()
|
|||
--p; // remove last tab
|
||||
p = safe_snprintf(p, end, "\n");
|
||||
|
||||
if (p <= end)
|
||||
if (p < end)
|
||||
completeWrite(&Modes.fatsv_out, p);
|
||||
else
|
||||
fprintf(stderr, "fatsv: output too large (max %d, overran by %d)\n", TSV_MAX_PACKET_SIZE, (int) (p - end));
|
||||
|
@ -2271,7 +2275,9 @@ static void writeFATSV()
|
|||
a->fatsv_emitted_mag_heading = a->mag_heading;
|
||||
a->fatsv_emitted_true_heading = a->true_heading;
|
||||
a->fatsv_emitted_airground = a->airground;
|
||||
a->fatsv_emitted_nav_altitude = a->nav_altitude;
|
||||
a->fatsv_emitted_nav_altitude_mcp = a->nav_altitude_mcp;
|
||||
a->fatsv_emitted_nav_altitude_fms = a->nav_altitude_fms;
|
||||
a->fatsv_emitted_nav_altitude_src = a->nav_altitude_src;
|
||||
a->fatsv_emitted_nav_heading = a->nav_heading;
|
||||
a->fatsv_emitted_nav_modes = a->nav_modes;
|
||||
a->fatsv_emitted_nav_qnh = a->nav_qnh;
|
||||
|
|
2
net_io.h
2
net_io.h
|
@ -87,8 +87,6 @@ void modesInitNet(void);
|
|||
void modesQueueOutput(struct modesMessage *mm, struct aircraft *a);
|
||||
void modesNetPeriodicWork(void);
|
||||
|
||||
void writeFATSVHeader();
|
||||
|
||||
// TODO: move these somewhere else
|
||||
char *generateAircraftJson(const char *url_path, int *len);
|
||||
char *generateStatsJson(const char *url_path, int *len);
|
||||
|
|
|
@ -11,8 +11,8 @@ then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
export DEBFULLNAME=${DEBFULLNAME:-FlightAware build automation}
|
||||
export DEBEMAIL=${DEBEMAIL:-adsb-devs@flightaware.com}
|
||||
export DEBFULLNAME="${DEBFULLNAME:-FlightAware build automation}"
|
||||
export DEBEMAIL="${DEBEMAIL:-adsb-devs@flightaware.com}"
|
||||
|
||||
TOP=`dirname $0`
|
||||
DIST=$1
|
||||
|
|
|
@ -384,7 +384,16 @@ PlaneObject.prototype.updateIcon = function() {
|
|||
var outline = (this.position_from_mlat ? OutlineMlatColor : OutlineADSBColor);
|
||||
var add_stroke = (this.selected && !SelectedAllPlanes) ? ' stroke="black" stroke-width="1px"' : '';
|
||||
var baseMarker = getBaseMarker(this.category, this.icaotype, this.typeDescription, this.wtc);
|
||||
var rotation = (this.track === null ? 0 : this.track);
|
||||
var rotation = this.track;
|
||||
if (rotation === null) {
|
||||
rotation = this.true_heading;
|
||||
}
|
||||
if (rotation === null) {
|
||||
rotation = this.mag_heading;
|
||||
}
|
||||
if (rotation === null) {
|
||||
rotation = 0;
|
||||
}
|
||||
//var transparentBorderWidth = (32 / baseMarker.scale / scaleFactor).toFixed(1);
|
||||
|
||||
var svgKey = col + '!' + outline + '!' + baseMarker.svg + '!' + add_stroke + "!" + scaleFactor;
|
||||
|
@ -445,7 +454,7 @@ PlaneObject.prototype.updateData = function(receiver_timestamp, data) {
|
|||
|
||||
var fields = ["alt_baro", "alt_geom", "gs", "ias", "tas", "track",
|
||||
"track_rate", "mag_heading", "true_heading", "mach",
|
||||
"roll", "nav_altitude", "nav_heading", "nav_modes",
|
||||
"roll", "nav_heading", "nav_modes",
|
||||
"nac_p", "nac_v", "nic_baro", "sil_type", "sil",
|
||||
"nav_qnh", "baro_rate", "geom_rate", "rc",
|
||||
"squawk", "category", "version"];
|
||||
|
@ -498,6 +507,15 @@ PlaneObject.prototype.updateData = function(receiver_timestamp, data) {
|
|||
this.altitude = null;
|
||||
}
|
||||
|
||||
// Pick a selected altitude
|
||||
if ('nav_altitude_fms' in data) {
|
||||
this.nav_altitude = data.nav_altitude_fms;
|
||||
} else if ('nav_altitude_mcp' in data) {
|
||||
this.nav_altitude = data.nav_altitude_mcp;
|
||||
} else {
|
||||
this.nav_altitude = null;
|
||||
}
|
||||
|
||||
// Pick vertical rate from either baro or geom rate
|
||||
// geometric rate is generally more reliable (smoothed etc)
|
||||
if ('geom_rate' in data) {
|
||||
|
|
|
@ -389,6 +389,9 @@ function start_load_history() {
|
|||
for (var i = 0; i < PositionHistorySize; i++) {
|
||||
load_history_item(i);
|
||||
}
|
||||
} else {
|
||||
// Nothing to load
|
||||
end_load_history();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
#include <libbladeRF.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// Polyfill for the older bladerf API
|
||||
#if defined(LIBBLADERF_API_VERSION) && (LIBBLADERF_API_VERSION < 0x02000000)
|
||||
typedef unsigned int bladerf_frequency;
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
const char *device_str;
|
||||
const char *fpga_path;
|
||||
|
@ -102,7 +107,7 @@ static void show_config()
|
|||
int status;
|
||||
|
||||
unsigned rate;
|
||||
unsigned freq;
|
||||
bladerf_frequency freq;
|
||||
bladerf_lpf_mode lpf_mode;
|
||||
unsigned lpf_bw;
|
||||
bladerf_lna_gain lna_gain;
|
||||
|
|
|
@ -362,10 +362,11 @@ void rtlsdrRun()
|
|||
|
||||
start_cpu_timing(&rtlsdr_thread_cpu);
|
||||
|
||||
while (!Modes.exit) {
|
||||
rtlsdr_read_async(RTLSDR.dev, rtlsdrCallback, NULL,
|
||||
/* MODES_RTL_BUFFERS */ 4,
|
||||
MODES_RTL_BUF_SIZE);
|
||||
rtlsdr_read_async(RTLSDR.dev, rtlsdrCallback, NULL,
|
||||
/* MODES_RTL_BUFFERS */ 4,
|
||||
MODES_RTL_BUF_SIZE);
|
||||
if (!Modes.exit) {
|
||||
fprintf(stderr, "rtlsdr: rtlsdr_read_async returned unexpectedly, probably lost the USB device, bailing out\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
148
track.c
148
track.c
|
@ -116,7 +116,9 @@ struct aircraft *trackCreateAircraft(struct modesMessage *mm) {
|
|||
F(squawk, 15, 70); // ADS-B or Mode S
|
||||
F(airground, 15, 70); // ADS-B or Mode S
|
||||
F(nav_qnh, 60, 70); // Comm-B only
|
||||
F(nav_altitude, 60, 70); // ADS-B or Comm-B
|
||||
F(nav_altitude_mcp, 60, 70); // ADS-B or Comm-B
|
||||
F(nav_altitude_fms, 60, 70); // ADS-B or Comm-B
|
||||
F(nav_altitude_src, 60, 70); // ADS-B or Comm-B
|
||||
F(nav_heading, 60, 70); // ADS-B or Comm-B
|
||||
F(nav_modes, 60, 70); // ADS-B or Comm-B
|
||||
F(cpr_odd, 60, 70); // ADS-B only
|
||||
|
@ -302,6 +304,18 @@ static int speed_check(struct aircraft *a, double lat, double lon, int surface)
|
|||
return inrange;
|
||||
}
|
||||
|
||||
// return 1 if left_rc is worse (less accurate) than right_rc
|
||||
static int rcIsWorse(int left_rc, int right_rc)
|
||||
{
|
||||
if (left_rc == 0 && right_rc == 0) // both unknown
|
||||
return 0;
|
||||
if (left_rc == 0)
|
||||
return 1; // left unknown < right known
|
||||
if (right_rc == 0)
|
||||
return 0; // left known > right unknown
|
||||
return (left_rc > right_rc);
|
||||
}
|
||||
|
||||
static int doGlobalCPR(struct aircraft *a, struct modesMessage *mm, double *lat, double *lon, unsigned *nic, unsigned *rc)
|
||||
{
|
||||
int result;
|
||||
|
@ -309,9 +323,9 @@ static int doGlobalCPR(struct aircraft *a, struct modesMessage *mm, double *lat,
|
|||
int surface = (mm->cpr_type == CPR_SURFACE);
|
||||
|
||||
// derive NIC, Rc from the worse of the two position
|
||||
// smaller NIC is worse; larger Rc is worse
|
||||
// smaller NIC is worse
|
||||
*nic = (a->cpr_even_nic < a->cpr_odd_nic ? a->cpr_even_nic : a->cpr_odd_nic);
|
||||
*rc = (a->cpr_even_rc > a->cpr_odd_rc ? a->cpr_even_rc : a->cpr_odd_rc);
|
||||
*rc = (rcIsWorse(a->cpr_even_rc, a->cpr_odd_rc) ? a->cpr_even_rc : a->cpr_odd_rc);
|
||||
|
||||
if (surface) {
|
||||
// surface global CPR
|
||||
|
@ -372,7 +386,7 @@ static int doGlobalCPR(struct aircraft *a, struct modesMessage *mm, double *lat,
|
|||
return result;
|
||||
|
||||
// check speed limit
|
||||
if (trackDataValid(&a->position_valid) && a->pos_nic >= *nic && a->pos_rc <= *rc && !speed_check(a, *lat, *lon, surface)) {
|
||||
if (trackDataValid(&a->position_valid) && a->pos_nic >= *nic && !rcIsWorse(a->pos_rc, *rc) && !speed_check(a, *lat, *lon, surface)) {
|
||||
Modes.stats_current.cpr_global_speed_checks++;
|
||||
return -2;
|
||||
}
|
||||
|
@ -404,7 +418,7 @@ static int doLocalCPR(struct aircraft *a, struct modesMessage *mm, double *lat,
|
|||
|
||||
if (a->pos_nic < *nic)
|
||||
*nic = a->pos_nic;
|
||||
if (a->pos_rc < *rc)
|
||||
if (rcIsWorse(a->pos_rc, *rc))
|
||||
*rc = a->pos_rc;
|
||||
|
||||
range_limit = 50e3;
|
||||
|
@ -454,7 +468,7 @@ static int doLocalCPR(struct aircraft *a, struct modesMessage *mm, double *lat,
|
|||
}
|
||||
|
||||
// check speed limit
|
||||
if (trackDataValid(&a->position_valid) && a->pos_nic >= *nic && a->pos_rc <= *rc && !speed_check(a, *lat, *lon, surface)) {
|
||||
if (trackDataValid(&a->position_valid) && a->pos_nic >= *nic && !rcIsWorse(a->pos_rc, *rc) && !speed_check(a, *lat, *lon, surface)) {
|
||||
#ifdef DEBUG_CPR_CHECKS
|
||||
fprintf(stderr, "Speed check for %06X with local decoding failed\n", a->addr);
|
||||
#endif
|
||||
|
@ -661,6 +675,8 @@ static unsigned compute_nic(unsigned metype, unsigned version, unsigned nic_a, u
|
|||
|
||||
static unsigned compute_rc(unsigned metype, unsigned version, unsigned nic_a, unsigned nic_b, unsigned nic_c)
|
||||
{
|
||||
// ED-102 Table 2-14, Table N-4, Table N-11
|
||||
|
||||
switch (metype) {
|
||||
case 5: // surface
|
||||
case 9: // airborne
|
||||
|
@ -696,7 +712,7 @@ static unsigned compute_rc(unsigned metype, unsigned version, unsigned nic_a, un
|
|||
} else if (nic_a && !nic_c) {
|
||||
return 556; // 555.6m, 0.3NM
|
||||
} else if (!nic_a && nic_c) {
|
||||
return 926; // 926m, 0.5NM
|
||||
return 1111; // 1111m, 0.6NM
|
||||
} else {
|
||||
return RC_UNKNOWN;
|
||||
}
|
||||
|
@ -709,16 +725,16 @@ static unsigned compute_rc(unsigned metype, unsigned version, unsigned nic_a, un
|
|||
if (nic_a && nic_b) {
|
||||
return 75;
|
||||
} else {
|
||||
return 186; // 370.4m, 0.2NM
|
||||
return 186; // 185.2m, 0.1NM
|
||||
}
|
||||
} else if (version == 1) {
|
||||
if (nic_a) {
|
||||
return 75;
|
||||
} else {
|
||||
return 186; // 370.4m, 0.2NM
|
||||
return 186; // 185.2m, 0.1NM
|
||||
}
|
||||
} else {
|
||||
return 186; // 370.4m, 0.2NM
|
||||
return 186; // 185.2m, 0.1NM
|
||||
}
|
||||
|
||||
case 12: // airborne
|
||||
|
@ -776,6 +792,81 @@ static unsigned compute_rc(unsigned metype, unsigned version, unsigned nic_a, un
|
|||
}
|
||||
}
|
||||
|
||||
// Map ADS-B v0 position message type to NACp value
|
||||
// returned computed NACp, or -1 if not a suitable message type
|
||||
static int compute_v0_nacp(struct modesMessage *mm)
|
||||
{
|
||||
if (mm->msgtype != 17 && mm->msgtype != 18) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ED-102A Table N-7
|
||||
switch (mm->metype) {
|
||||
case 0: return 0;
|
||||
case 5: return 11;
|
||||
case 6: return 10;
|
||||
case 7: return 8;
|
||||
case 8: return 0;
|
||||
case 9: return 11;
|
||||
case 10: return 10;
|
||||
case 11: return 8;
|
||||
case 12: return 7;
|
||||
case 13: return 6;
|
||||
case 14: return 5;
|
||||
case 15: return 4;
|
||||
case 16: return 1;
|
||||
case 17: return 1;
|
||||
case 18: return 0;
|
||||
case 20: return 11;
|
||||
case 21: return 10;
|
||||
case 22: return 0;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Map ADS-B v0 position message type to SIL value
|
||||
// returned computed SIL, or -1 if not a suitable message type
|
||||
static int compute_v0_sil(struct modesMessage *mm)
|
||||
{
|
||||
if (mm->msgtype != 17 && mm->msgtype != 18) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ED-102A Table N-8
|
||||
switch (mm->metype) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
return 2;
|
||||
|
||||
case 18:
|
||||
return 0;
|
||||
|
||||
case 20:
|
||||
case 21:
|
||||
return 2;
|
||||
|
||||
case 22:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void compute_nic_rc_from_message(struct modesMessage *mm, struct aircraft *a, unsigned *nic, unsigned *rc)
|
||||
{
|
||||
int nic_a = (trackDataValid(&a->nic_a_valid) && a->nic_a);
|
||||
|
@ -861,6 +952,23 @@ struct aircraft *trackUpdateFromMessage(struct modesMessage *mm)
|
|||
}
|
||||
}
|
||||
|
||||
// fill in ADS-B v0 NACp, SIL from position message type
|
||||
if (a->adsb_version == 0 && !mm->accuracy.nac_p_valid) {
|
||||
int computed_nacp = compute_v0_nacp(mm);
|
||||
if (computed_nacp != -1) {
|
||||
mm->accuracy.nac_p_valid = 1;
|
||||
mm->accuracy.nac_p = computed_nacp;
|
||||
}
|
||||
}
|
||||
|
||||
if (a->adsb_version == 0 && mm->accuracy.sil_type == SIL_INVALID) {
|
||||
int computed_sil = compute_v0_sil(mm);
|
||||
if (computed_sil != -1) {
|
||||
mm->accuracy.sil_type = SIL_UNKNOWN;
|
||||
mm->accuracy.sil = computed_sil;
|
||||
}
|
||||
}
|
||||
|
||||
if (mm->altitude_baro_valid && accept_data(&a->altitude_baro_valid, mm->source)) {
|
||||
int alt = altitude_to_feet(mm->altitude_baro, mm->altitude_baro_unit);
|
||||
if (a->modeC_hit) {
|
||||
|
@ -985,12 +1093,16 @@ struct aircraft *trackUpdateFromMessage(struct modesMessage *mm)
|
|||
memcpy(a->callsign, mm->callsign, sizeof(a->callsign));
|
||||
}
|
||||
|
||||
// prefer MCP over FMS
|
||||
// unless the source says otherwise
|
||||
if (mm->nav.mcp_altitude_valid && mm->nav.altitude_source != NAV_ALT_FMS && accept_data(&a->nav_altitude_valid, mm->source)) {
|
||||
a->nav_altitude = mm->nav.mcp_altitude;
|
||||
} else if (mm->nav.fms_altitude_valid && accept_data(&a->nav_altitude_valid, mm->source)) {
|
||||
a->nav_altitude = mm->nav.fms_altitude;
|
||||
if (mm->nav.mcp_altitude_valid && accept_data(&a->nav_altitude_mcp_valid, mm->source)) {
|
||||
a->nav_altitude_mcp = mm->nav.mcp_altitude;
|
||||
}
|
||||
|
||||
if (mm->nav.fms_altitude_valid && accept_data(&a->nav_altitude_fms_valid, mm->source)) {
|
||||
a->nav_altitude_fms = mm->nav.fms_altitude;
|
||||
}
|
||||
|
||||
if (mm->nav.altitude_source != NAV_ALT_INVALID && accept_data(&a->nav_altitude_src_valid, mm->source)) {
|
||||
a->nav_altitude_src = mm->nav.altitude_source;
|
||||
}
|
||||
|
||||
if (mm->nav.heading_valid && accept_data(&a->nav_heading_valid, mm->source)) {
|
||||
|
@ -1205,7 +1317,9 @@ static void trackRemoveStaleAircraft(uint64_t now)
|
|||
EXPIRE(squawk);
|
||||
EXPIRE(airground);
|
||||
EXPIRE(nav_qnh);
|
||||
EXPIRE(nav_altitude);
|
||||
EXPIRE(nav_altitude_mcp);
|
||||
EXPIRE(nav_altitude_fms);
|
||||
EXPIRE(nav_altitude_src);
|
||||
EXPIRE(nav_heading);
|
||||
EXPIRE(nav_modes);
|
||||
EXPIRE(cpr_odd);
|
||||
|
|
14
track.h
14
track.h
|
@ -151,8 +151,14 @@ struct aircraft {
|
|||
data_validity nav_qnh_valid;
|
||||
float nav_qnh; // Altimeter setting (QNH/QFE), millibars
|
||||
|
||||
data_validity nav_altitude_valid;
|
||||
unsigned nav_altitude; // FMS or FCU selected altitude
|
||||
data_validity nav_altitude_mcp_valid;
|
||||
unsigned nav_altitude_mcp; // FCU/MCP selected altitude
|
||||
|
||||
data_validity nav_altitude_fms_valid;
|
||||
unsigned nav_altitude_fms; // FMS selected altitude
|
||||
|
||||
data_validity nav_altitude_src_valid;
|
||||
nav_altitude_source_t nav_altitude_src; // source of altitude used by automation
|
||||
|
||||
data_validity nav_heading_valid;
|
||||
float nav_heading; // target heading, degrees (0-359)
|
||||
|
@ -220,7 +226,9 @@ struct aircraft {
|
|||
unsigned fatsv_emitted_tas; // -"- TAS
|
||||
float fatsv_emitted_mach; // -"- Mach number
|
||||
airground_t fatsv_emitted_airground; // -"- air/ground state
|
||||
unsigned fatsv_emitted_nav_altitude; // -"- target altitude
|
||||
unsigned fatsv_emitted_nav_altitude_mcp; // -"- MCP altitude
|
||||
unsigned fatsv_emitted_nav_altitude_fms; // -"- FMS altitude
|
||||
unsigned fatsv_emitted_nav_altitude_src; // -"- automation altitude source
|
||||
float fatsv_emitted_nav_heading; // -"- target heading
|
||||
nav_modes_t fatsv_emitted_nav_modes; // -"- enabled navigation modes
|
||||
float fatsv_emitted_nav_qnh; // -"- altimeter setting
|
||||
|
|
Loading…
Reference in a new issue