Implement a remote interactive screen

No changes to dump1090, (except the version number)

Include a sample Linux batch start file called dump1090.sh for use when
running dump1090 headless. This file needs to be copied to the
/etc/init.d/ subdirectory on your raspberry pi, and marked as
executable. Then when you re-start your RPi, dump1090 will start-up
auto-magically and run as a sort of server to allow both local and
remote connection to it's various internet ports.

Modified the Makefile to build a new headless helper application called
view1090

Added view1090. This is an executable that allows you to connect to
dump1090 when it is running and 'see' the interactive screen display.
The default is to try and connect to dump1090 on IP address 127.0.0.1
port 30005. This should work if you are running on the same RPi as
dump1090 and using the default dump1090 port settings. However, if
you're running on a different machine you will have to specify the IP
address of the RPi running dump1090 using the --net-bo-ipaddr switch.
Something like "view1090 --net-bo-ipaddr 192.168.2.65" . You may also
have to sudo it, depending on your privilige settings.

I've also compiled view1090 as a Wiin32 exe, so you should be able to
run it under any 32 bit version of Microsoft Windows - i.e. Win95, Win
2K, Win XP, Win 7 etc.  It may work on Win 8 and 64 bit Windows, but I
haven't tried it. The Win32 version is compiled from the same source, so
takes all the same command line switches.
This commit is contained in:
Malcolm Robb 2013-09-24 18:37:54 +01:00
parent 03c16aa19a
commit 0430323014
6 changed files with 392 additions and 3 deletions

View file

@ -15,7 +15,7 @@ LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
CC=gcc
all: dump1090
all: dump1090 view1090
%.o: %.c
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
@ -23,5 +23,8 @@ all: dump1090
dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
$(CC) -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS)
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
$(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS)
clean:
rm -f *.o dump1090
rm -f *.o dump1090 view1090

BIN
Release/view1090.exe Normal file

Binary file not shown.

View file

@ -37,7 +37,7 @@
// 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
//
#define MODES_DUMP1090_VERSION "1.07.2009.13"
#define MODES_DUMP1090_VERSION "1.07.2109.13"
// ============================= Include files ==========================
@ -255,6 +255,9 @@ struct { // Internal state
int rawOutUsed; // How much of the buffer is currently used
char *beastOut; // Buffer for building beast output data
int beastOutUsed; // How much if the buffer is currently used
#ifdef _WIN32
WSADATA wsaData; // Windows socket initialisation
#endif
// Configuration
char *filename; // Input form file, --ifile option

74
dump1090.sh Normal file
View file

@ -0,0 +1,74 @@
#!/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="dump1090"
PROG_PATH="/home/pi/dump1090"
PROG_ARGS="--quiet --net --net-ro-size 500 --net-ro-rate 5"
PIDFILE="/var/run/dump1090.pid"
start() {
if [ -e $PIDFILE ]; then
## Program is running, exit with error.
echo "Error! $PROG is currently running!" 1>&2
exit 1
else
## Change from /dev/null to something like /var/log/$PROG if you want to save output.
cd $PROG_PATH
./$PROG $PROG_ARGS 2>&1 >/dev/null &
echo "$PROG started"
touch $PIDFILE
fi
}
stop() {
if [ -e $PIDFILE ]; then
## Program is running, so stop it
echo "$PROG is running"
killall $PROG
rm -f $PIDFILE
echo "$PROG stopped"
else
## Program is not running, exit with error.
echo "Error! $PROG not started!" 1>&2
exit 1
fi
}
## Check to see if we are running as root first.
## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
case "$1" in
start)
start
exit 0
;;
stop)
stop
exit 0
;;
reload|restart|force-reload)
stop
start
exit 0
;;
**)
echo "Usage: $0 {start|stop|reload}" 1>&2
exit 1
;;
esac
#

227
view1090.c Normal file
View file

@ -0,0 +1,227 @@
// view1090, a Mode S messages viewer for dump1090 devices.
//
// Copyright (C) 2013 by Malcolm Robb <Support@ATTAvionics.com>
//
// 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 "view1090.h"
//
// ============================= Utility functions ==========================
//
void sigintHandler(int dummy) {
NOTUSED(dummy);
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
Modes.exit = 1; // Signal to threads that we are done
}
//
// =============================== Initialization ===========================
//
void view1090InitConfig(void) {
// Default everything to zero/NULL
memset(&Modes, 0, sizeof(Modes));
memset(&View1090, 0, sizeof(View1090));
// Now initialise things that should not be 0/NULL to their defaults
Modes.check_crc = 1;
strcpy(View1090.net_input_beast_ipaddr,VIEW1090_NET_OUTPUT_IP_ADDRESS);
Modes.net_input_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
Modes.interactive_rows = MODES_INTERACTIVE_ROWS;
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;
Modes.interactive = 1;
}
//
//=========================================================================
//
void view1090Init(void) {
// Allocate the various buffers used by Modes
if ( NULL == (Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2)))
{
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;
}
// Prepare error correction tables
modesInitErrorInfo();
}
//
// ================================ Main ====================================
//
void showHelp(void) {
printf(
"-----------------------------------------------------------------------------\n"
"| view1090 dump1090 Viewer 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"
"--modeac Enable decoding of SSR modes 3/A & 3/C\n"
"--net-bo-ipaddr <IPv4> TCP Beast output listen IPv4 (default: 127.0.0.1)\n"
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
"--lat <latitude> Reference/receiver latitide for surface posn (opt)\n"
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
"--no-crc-check Disable messages with broken CRC (discouraged)\n"
"--no-fix Disable single-bits error correction using CRC\n"
"--fix Enable single-bits error correction using CRC\n"
"--aggressive More CPU for more messages (two bits fixes, ...)\n"
"--metric Use metric units (meters, km/h, ...)\n"
"--help Show this help\n"
);
}
//
//=========================================================================
//
int main(int argc, char **argv) {
int j, fd;
struct client *c;
// Set sane defaults
view1090InitConfig();
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],"--net-bo-port") && more) {
Modes.net_input_beast_port = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) {
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
} else if (!strcmp(argv[j],"--modeac")) {
Modes.mode_ac = 1;
} else if (!strcmp(argv[j],"--interactive-rows") && more) {
Modes.interactive_rows = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--interactive")) {
Modes.interactive = 1;
} else if (!strcmp(argv[j],"--interactive-ttl") && more) {
Modes.interactive_display_ttl = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--interactive-rtl1090")) {
Modes.interactive = 1;
Modes.interactive_rtl1090 = 1;
} 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],"--metric")) {
Modes.metric = 1;
} else if (!strcmp(argv[j],"--no-crc-check")) {
Modes.check_crc = 0;
} else if (!strcmp(argv[j],"--fix")) {
Modes.nfix_crc = 1;
} else if (!strcmp(argv[j],"--no-fix")) {
Modes.nfix_crc = 0;
} else if (!strcmp(argv[j],"--aggressive")) {
Modes.nfix_crc = MODES_MAX_BITERRORS;
} else if (!strcmp(argv[j],"--help")) {
showHelp();
exit(0);
} else {
fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]);
showHelp();
exit(1);
}
}
// Initialization
view1090Init();
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) {
fprintf(stderr, "Failed to connect to %s:%d\n", View1090.net_input_beast_ipaddr, Modes.net_input_beast_port);
exit(1);
}
//
// Setup a service callback client structure for a beast binary input (from dump1090)
// This is a bit dodgy under Windows. The fd parameter is a handle to the internet
// socket on which we are receiving data. Under Linux, these seem to start at 0 and
// count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0.
// dump1090 limits fd to values less than 1024, and then uses the fd parameter to
// index into an array of clients. This is ok-ish if handles are allocated up from 0.
// However, there is no gaurantee that Windows will behave like this, and if Windows
// allocates a handle greater than 1024, then dump1090 won't like it. On my test machine,
// the first Windows handle is usually in the 0x54 (84 decimal) region.
if (fd >= MODES_NET_MAX_FD) { // Max number of clients reached
close(fd);
exit(1);
}
c = (struct client *) malloc(sizeof(*c));
c->buflen = 0;
c->fd =
c->service =
Modes.bis = fd;
Modes.clients[fd] = c;
if (Modes.maxfd < fd) {
Modes.maxfd = fd;
}
// Keep going till the user does something that stops us
while (!Modes.exit) {
modesReadFromClient(c,"",decodeBinMessage);
interactiveRemoveStaleAircrafts();
interactiveShowData();
}
// The user has stopped us, so close any socket we opened
if (fd != ANET_ERR)
{close(fd);}
pthread_exit(0);
return (0);
}
//
//=========================================================================
//

82
view1090.h Normal file
View file

@ -0,0 +1,82 @@
// view1090, a Mode S messages viewer for dump1090 devices.
//
// Copyright (C) 2013 by Malcolm Robb <Support@ATTAvionics.com>
//
// 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.
//
#ifndef __VIEW1090_H
#define __VIEW1090_H
// ============================= Include files ==========================
#include "dump1090.h"
#ifndef _WIN32
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include "rtl-sdr.h"
#include "anet.h"
#else
#include "winstubs.h" //Put everything Windows specific in here
#endif
// ============================= #defines ===============================
#define VIEW1090_NET_OUTPUT_IP_ADDRESS "127.0.0.1"
#define NOTUSED(V) ((void) V)
// ======================== structure declarations ========================
// Program global state
struct { // Internal state
// Networking
char net_input_beast_ipaddr[32]; // IPv4 address or network name of server/RPi
} View1090;
// ======================== function declarations =========================
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif // __VIEW1090_H