massive refactor to c++ in progress, doesn't build now

Former-commit-id: bbd3fe3c0438b9f8d2188b8d1f5ffc70616a789f
Former-commit-id: d19da520563adeb80996df92c65ba5e1e6785596
This commit is contained in:
nathan 2020-03-07 17:22:20 -08:00
parent cb62238efd
commit af9cfce3ff
21 changed files with 1840 additions and 711 deletions

33
Aircraft.cpp Normal file
View file

@ -0,0 +1,33 @@
#include "Aircraft.h"
Aircraft::Aircraft(struct aircraft *a) {
addr = a->addr;
created = 0;
oldIdx = 0;
prev_seen = 0;
x = 0;
y = 0;
cx = 0;
cy = 0;
ox = 0;
oy = 0;
dox = 0;
doy = 0;
ddox = 0;
ddoy = 0;
memset(oldLon, 0, sizeof(oldLon));
memset(oldLat, 0, sizeof(oldLat));
memset(oldHeading, 0, sizeof(oldHeading));
}
Aircraft::~Aircraft() {
free(oldLat);
free(oldLon);
free(oldHeading);
}

43
Aircraft.h Normal file
View file

@ -0,0 +1,43 @@
#include <stdint.h>
#include "defs.h"
#include <ctime>
class Aircraft {
public:
uint32_t addr; // ICAO address
char flight[16]; // Flight number
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
double messageRate;
int altitude; // Altitude
int speed; // Velocity
int track; // Angle of flight
int vert_rate; // Vertical rate.
time_t seen; // Time at which the last packet was received
time_t seenLatLon; // Time at which the last packet was received
time_t prev_seen;
double lat, lon; // Coordinated obtained from CPR encoded data
//history
float oldLon[TRAIL_LENGTH];
float oldLat[TRAIL_LENGTH];
float oldHeading[TRAIL_LENGTH];
time_t oldSeen[TRAIL_LENGTH];
uint8_t oldIdx;
uint64_t created;
uint64_t msSeen;
uint64_t msSeenLatLon;
int live;
struct Aircraft *next; // Next aircraft in our linked list
//// label stuff -> should go to aircraft icon class
int x, y, cx, cy, w, h;
float ox, oy, dox, doy, ddox, ddoy;
float pressure;
/// methods
Aircraft(struct aircraft *a);
~Aircraft();
};

131
AircraftData.cpp Normal file
View file

@ -0,0 +1,131 @@
#include "AircraftData.h"
//
//carried over from view1090.c
//
int AircraftData::setupConnection(struct client *c) {
int fd;
// 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) {
anetNonBlock(modes.aneterr, fd);
//
// 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.
c->next = NULL;
c->buflen = 0;
c->fd =
c->service =
modes.bis = fd;
modes.clients = c;
}
return fd;
}
//
// end view1090.c
//
void AircraftData::initialize() {
// 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);
// Prepare error correction tables
modesInitErrorInfo(&(modes));
}
void AircraftData::connect() {
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
c = (struct client *) malloc(sizeof(*c));
while(1) {
if ((fd = setupConnection(c)) == ANET_ERR) {
fprintf(stderr, "Waiting on %s:%d\n", View1090.net_input_beast_ipaddr, modes.net_input_beast_port);
sleep(1);
} else {
break;
}
}
}
void AircraftData::disconnect() {
if (fd != ANET_ERR)
{close(fd);}
}
void AircraftData::update() {
if ((fd == ANET_ERR) || (recv(c->fd, pk_buf, sizeof(pk_buf), MSG_PEEK | MSG_DONTWAIT) == 0)) {
free(c);
usleep(1000000);
c = (struct client *) malloc(sizeof(*c));
fd = setupConnection(c);
return;
}
modesReadFromClient(&modes, c,"",decodeBinMessage);
interactiveRemoveStaleAircrafts(&modes);
aircraftList.update();
}
AircraftData::AircraftData(){
// 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 = 0;
modes.quiet = 1;
// Map options
appData.maxDist = 25.0;
appData.centerLon = modes.fUserLon;
appData.centerLat = modes.fUserLat;
// Display options
appData.screen_uiscale = 1;
appData.screen_width = 0;
appData.screen_height = 0;
appData.screen_depth = 32;
appData.fullscreen = 0;
// Initialize status
Status.msgRate = 0;
Status.avgSig = 0;
Status.numPlanes = 0;
Status.numVisiblePlanes = 0;
Status.maxDist = 0;
selectedAircraft = NULL;
}

34
AircraftData.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef AIRCRAFTDATA_H
#define AIRCRAFTDATA_H
#include "dump1090.h"
#include "view1090.h"
#include "structs.h"
#include "AircraftList.h"
class AircraftData {
private:
//from view1090.c
int setupConnection(struct client *c);
//
struct client *c;
int fd;
char pk_buf[8];
public:
void initialize();
void connect();
void disconnect();
void update();
AircraftData();
AircraftList aircraftList;
Aircraft *selectedAircraft;
Modes modes;
};
#endif

View file

@ -1,4 +1,4 @@
#include "structs.h"
#include "AircraftList.h"
#include "dump1090.h"
static uint64_t mstime(void) {
@ -11,8 +11,8 @@ static uint64_t mstime(void) {
return mst;
}
PlaneObj *findPlaneObj(uint32_t addr) {
PlaneObj *p = appData.planes;
Aircraft *AircraftList::find(uint32_t addr) {
Aircraft *p = head;
while(p) {
if (p->addr == addr) return (p);
@ -21,39 +21,12 @@ PlaneObj *findPlaneObj(uint32_t addr) {
return (NULL);
}
PlaneObj *createPlaneObj(struct aircraft *a) {
PlaneObj *p = (PlaneObj *) malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
p->addr = a->addr;
p->created = 0;
p->oldIdx = 0;
p->prev_seen = 0;
p->x = 0;
p->y = 0;
p->cx = 0;
p->cy = 0;
p->ox = 0;
p->oy = 0;
p->dox = 0;
p->doy = 0;
p->ddox = 0;
p->ddoy = 0;
memset(p->oldLon, 0, sizeof(p->oldLon));
memset(p->oldLat, 0, sizeof(p->oldLat));
memset(p->oldHeading, 0, sizeof(p->oldHeading));
return (p);
}
void updatePlanes() {
void AircraftList::update
() {
//instead of this, net_io should call this class directly to update info
struct aircraft *a = modes.aircrafts;
PlaneObj *p = appData.planes;
Aircraft *p = head;
while(p) {
p->live = 0;
@ -62,11 +35,12 @@ void updatePlanes() {
while(a) {
p = findPlaneObj(a->addr);
p = find(a->addr);
if (!p) {
p = createPlaneObj(a);
p->next = appData.planes;
appData.planes = p;
//p = createPlaneObj(a);
p = new Aircraft(a);
p->next = head;
head = p;
} else {
p->prev_seen = p->seen;
}
@ -113,18 +87,18 @@ void updatePlanes() {
a = a->next;
}
p = appData.planes;
PlaneObj *prev = NULL;
p = head;
Aircraft *prev = NULL;
while(p) {
if(!p->live) {
if (!prev) {
appData.planes = p->next;
free(p);
p = appData.planes;
head = p->next;
delete(p);
p = head;
} else {
prev->next = p->next;
free(p);
delete(p);
p = prev->next;
}
} else {
@ -133,3 +107,15 @@ void updatePlanes() {
}
}
}
AircraftList::AircraftList() {
head = NULL;
}
AircraftList::~AircraftList() {
while(head != NULL) {
Aircraft *temp = head;
head = head->next;
delete(temp);
}
}

12
AircraftList.h Normal file
View file

@ -0,0 +1,12 @@
#include "Aircraft.h"
class AircraftList {
public:
Aircraft *head;
Aircraft *find(uint32_t addr);
void update();
AircraftList();
~AircraftList();
};

View file

@ -1,6 +1,8 @@
#include "structs.h"
#include "view1090.h"
#include "Input.h"
static uint64_t mstime(void) {
struct timeval tv;
uint64_t mst;
@ -11,7 +13,7 @@ static uint64_t mstime(void) {
return mst;
}
void getInput()
void Input::getInput()
{
SDL_Event event;
@ -60,7 +62,7 @@ void getInput()
appData.touchy = event.motion.y;
appData.tapCount = event.button.clicks;
registerClick();
view->registerClick();
appData.isDragging = 0;
break;
@ -72,9 +74,13 @@ void getInput()
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) {
appData.isDragging = 1;
moveCenterRelative(event.motion.xrel, event.motion.yrel);
view->moveCenterRelative(event.motion.xrel, event.motion.yrel);
}
break;
}
}
}
Input::Input(View *view) {
this->view = view;
}

17
Input.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef INPUT_H
#define INPUT
#include "AircraftData.h"
#include "View.h"
class Input {
public:
void getInput();
//should input know about view?
Input(View *view);
View *view;
};
#endif

View file

@ -2,19 +2,18 @@
# 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=view1090
CFLAGS=-O2 -g -Wall -W
LIBS=-lm -lSDL2 -lSDL2_ttf -lSDL2_gfx
CC=g++
all: view1090
all: map1090
%.o: %.c
%.o: %.c %.cpp
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
view1090: view1090.o anet.o interactive.o planeObj.o mode_ac.o mode_s.o net_io.o input.o draw.o font.o init.o mapdata.o status.o parula.o monokai.o
$(CC) -g -o view1090 view1090.o anet.o interactive.o planeObj.o mode_ac.o mode_s.o net_io.o input.o draw.o font.o init.o mapdata.o status.o parula.o monokai.o $(LIBS) $(LDFLAGS)
map1090: map1090.o AircraftData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o font.o init.o mapdata.o status.o parula.o monokai.o
$(CC) -g -o map1090 map1090.o AircraftData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o font.o init.o mapdata.o status.o parula.o monokai.o $(LIBS) $(LDFLAGS)
clean:
rm -f *.o view1090
rm -f *.o map1090

View file

@ -7,6 +7,8 @@
#include "parula.h"
#include "monokai.h"
#include "View.h"
static uint64_t mstime(void) {
struct timeval tv;
uint64_t mst;
@ -17,11 +19,11 @@ static uint64_t mstime(void) {
return mst;
}
float sign(float x) {
static float sign(float x) {
return (x > 0) - (x < 0);
}
float clamp(float in, float min, float max) {
static float clamp(float in, float min, float max) {
float out = in;
if(in < min) {
@ -35,7 +37,7 @@ float clamp(float in, float min, float max) {
return out;
}
void CROSSVP(float *v, float *u, float *w)
static void CROSSVP(float *v, float *u, float *w)
{
v[0] = u[1]*w[2] - u[2]*(w)[1];
v[1] = u[2]*w[0] - u[0]*(w)[2];
@ -141,7 +143,7 @@ SDL_Color hsv2SDLColor(float h, float s, float v)
return out;
}
int screenDist(float d) {
int View::screenDist(float d) {
float scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
return round(0.95 * scale_factor * 0.5 * fabs(d) / appData.maxDist);
}
@ -157,7 +159,7 @@ void pxFromLonLat(float *dx, float *dy, float lon, float lat) {
*dy = 6371.0 * (lat - appData.centerLat) * M_PI / 180.0f;
}
void latLonFromScreenCoords(float *lat, float *lon, int x, int y) {
void View::latLonFromScreenCoords(float *lat, float *lon, int x, int y) {
float scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
float dx = appData.maxDist * (x - (appData.screen_width>>1)) / (0.95 * scale_factor * 0.5 );
@ -168,12 +170,12 @@ void latLonFromScreenCoords(float *lat, float *lon, int x, int y) {
}
void screenCoords(int *outX, int *outY, float dx, float dy) {
void View::screenCoords(int *outX, int *outY, float dx, float dy) {
*outX = (appData.screen_width>>1) + ((dx>0) ? 1 : -1) * screenDist(dx);
*outY = (appData.screen_height * CENTEROFFSET) + ((dy>0) ? -1 : 1) * screenDist(dy);
}
int outOfBounds(int x, int y) {
int View::outOfBounds(int x, int y) {
if(x < 0 || x >= appData.screen_width || y < 0 || y >= appData.screen_height ) {
return 1;
} else {
@ -181,7 +183,7 @@ int outOfBounds(int x, int y) {
}
}
void drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeColor) {
void View::drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeColor) {
float arrowWidth = 6.0 * appData.screen_uiscale;
@ -239,7 +241,7 @@ void drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeCo
*returny = y3;
}
void drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor)
void View::drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor)
{
float body = 8.0 * appData.screen_uiscale;
float wing = 6.0 * appData.screen_uiscale;
@ -286,7 +288,7 @@ void drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor)
filledTrigonRGBA (appData.renderer, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
void drawTrail(float *oldDx, float *oldDy, float *oldHeading, time_t * oldSeen, int idx) {
void View::drawTrail(float *oldDx, float *oldDy, float *oldHeading, time_t * oldSeen, int idx) {
int currentIdx, prevIdx;
@ -377,7 +379,7 @@ void drawTrail(float *oldDx, float *oldDy, float *oldHeading, time_t * oldSeen,
}
}
void drawScaleBars()
void View::drawScaleBars()
{
int scalePower = 0;
int scaleBarDist = screenDist((float)pow(10,scalePower));
@ -407,7 +409,7 @@ void drawScaleBars()
lineRGBA(appData.renderer,10,10+5*appData.screen_uiscale,10+scaleBarDist,10+5*appData.screen_uiscale, style.scaleBarColor.r, style.scaleBarColor.g, style. scaleBarColor.b, 255);
}
void drawPolys(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max) {
void View::drawPolys(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max) {
if(tree == NULL) {
return;
}
@ -498,7 +500,7 @@ void drawPolys(QuadTree *tree, float screen_lat_min, float screen_lat_max, float
}
}
void drawGeography() {
void View::drawGeography() {
float screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max;
latLonFromScreenCoords(&screen_lat_min, &screen_lon_min, 0, appData.screen_height * -0.2);
@ -507,7 +509,7 @@ void drawGeography() {
drawPolys(&(appData.root), screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
}
void drawSignalMarks(PlaneObj *p, int x, int y) {
void View::drawSignalMarks(Aircraft *p, int x, int y) {
unsigned char * pSig = p->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 3;
@ -525,7 +527,7 @@ void drawSignalMarks(PlaneObj *p, int x, int y) {
}
void drawPlaneText(PlaneObj *p) {
void View::drawPlaneText(Aircraft *p) {
int maxCharCount = 0;
int currentCharCount;
@ -599,7 +601,7 @@ void drawPlaneText(PlaneObj *p) {
p->h = currentLine * appData.mapFontHeight;
}
void drawSelectedPlaneText(PlaneObj *p) {
void View::drawSelectedAircraftText(Aircraft *p) {
if(p == NULL) {
return;
}
@ -653,12 +655,12 @@ void drawSelectedPlaneText(PlaneObj *p) {
}
}
void resolveLabelConflicts() {
PlaneObj *p = appData.planes;
void View::resolveLabelConflicts() {
Aircraft *p = aircraftData->aircraftList.head;
while(p) {
PlaneObj *check_p = appData.planes;
Aircraft *check_p = aircraftData->aircraftList.head;
int p_left = p->x - 10 * appData.screen_uiscale;
int p_right = p->x + p->w + 10 * appData.screen_uiscale;
@ -747,7 +749,7 @@ void resolveLabelConflicts() {
check_p = check_p -> next;
}
check_p = appData.planes;
check_p = aircraftData->aircraftList.head;
//check against plane icons (include self)
@ -803,7 +805,7 @@ void resolveLabelConflicts() {
//update
p = appData.planes;
p = aircraftData->aircraftList.head;
while(p) {
//incorporate acceleration from label conflict resolution
@ -843,8 +845,8 @@ void resolveLabelConflicts() {
}
void drawPlanes() {
PlaneObj *p = appData.planes;
void View::drawPlanes() {
Aircraft *p = aircraftData->aircraftList.head;
time_t now = time(NULL);
SDL_Color planeColor;
@ -858,12 +860,12 @@ void drawPlanes() {
p = p->next;
}
if(appData.selectedPlane) {
appData.mapTargetLon = appData.selectedPlane->lon;
appData.mapTargetLat = appData.selectedPlane->lat;
if(aircraftData->selectedAircraft) {
appData.mapTargetLon = aircraftData->selectedAircraft->lon;
appData.mapTargetLat = aircraftData->selectedAircraft->lat;
}
p = appData.planes;
p = aircraftData->aircraftList.head;
while(p) {
if ((now - p->seen) < modes.interactive_display_ttl) {
@ -900,7 +902,7 @@ void drawPlanes() {
usey = y + (mstime() - p->msSeenLatLon) * vely;
}
if(p == appData.selectedPlane) {
if(p == aircraftData->selectedAircraft) {
// this logic should be in input, register a callback for click?
float elapsed = mstime() - appData.touchDownTime;
@ -935,7 +937,7 @@ void drawPlanes() {
p->cy = usey;
}
if(p != appData.selectedPlane) {
if(p != aircraftData->selectedAircraft) {
drawPlaneText(p);
}
@ -946,7 +948,7 @@ void drawPlanes() {
p = p->next;
}
drawSelectedPlaneText(appData.selectedPlane);
drawSelectedAircraftText(aircraftData->selectedAircraft);
if(appData.touchx && appData.touchy) {
@ -963,7 +965,7 @@ void drawPlanes() {
}
}
void animateCenterAbsolute(float x, float y) {
void View::animateCenterAbsolute(float x, float y) {
float scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
float dx = -1.0 * (0.75*(double)appData.screen_width / (double)appData.screen_height) * (x - appData.screen_width/2) * appData.maxDist / (0.95 * scale_factor * 0.5);
@ -985,7 +987,7 @@ void animateCenterAbsolute(float x, float y) {
}
void moveCenterAbsolute(float x, float y) {
void View::moveCenterAbsolute(float x, float y) {
float scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
float dx = -1.0 * (0.75*(double)appData.screen_width / (double)appData.screen_height) * (x - appData.screen_width/2) * appData.maxDist / (0.95 * scale_factor * 0.5);
@ -1007,7 +1009,7 @@ void moveCenterAbsolute(float x, float y) {
appData.mapMoved = 1;
}
void moveCenterRelative(float dx, float dy) {
void View::moveCenterRelative(float dx, float dy) {
//
// need to make lonlat to screen conversion class - this is just the inverse of the stuff in draw.c, without offsets
//
@ -1033,7 +1035,7 @@ void moveCenterRelative(float dx, float dy) {
appData.mapMoved = 1;
}
void zoomMapToTarget() {
void View::zoomMapToTarget() {
if(appData.mapTargetMaxDist) {
if(fabs(appData.mapTargetMaxDist - appData.maxDist) > 0.0001) {
appData.maxDist += 0.1 * (appData.mapTargetMaxDist - appData.maxDist);
@ -1043,7 +1045,7 @@ void zoomMapToTarget() {
}
}
void moveMapToTarget() {
void View::moveMapToTarget() {
if(appData.mapTargetLon && appData.mapTargetLat) {
if(fabs(appData.mapTargetLon - appData.centerLon) > 0.0001 || fabs(appData.mapTargetLat - appData.centerLat) > 0.0001) {
appData.centerLon += 0.1 * (appData.mapTargetLon- appData.centerLon);
@ -1057,7 +1059,7 @@ void moveMapToTarget() {
}
}
void drawMouse() {
void View::drawMouse() {
if(appData.mouseMovedTime == 0 || (mstime() - appData.mouseMovedTime) > 1000) {
appData.mouseMovedTime = 0;
return;
@ -1069,10 +1071,10 @@ void drawMouse() {
lineRGBA(appData.renderer, appData.mousex, appData.mousey - 10 * appData.screen_uiscale, appData.mousex, appData.mousey + 10 * appData.screen_uiscale, white.r, white.g, white.b, alpha);
}
void registerClick() {
void View::registerClick() {
if(appData.tapCount == 1 && appData.isDragging == 0) {
PlaneObj *p = appData.planes;
PlaneObj *selection = NULL;
Aircraft *p = aircraftData->aircraftList.head;
Aircraft *selection = NULL;
while(p) {
if(appData.touchx && appData.touchy) {
@ -1091,8 +1093,8 @@ void registerClick() {
p = p->next;
}
//if(appData.selectedPlane == NULL) {
appData.selectedPlane = selection;
//if(aircraftData->selectedAircraft == NULL) {
aircraftData->selectedAircraft = selection;
//}
} else if(appData.tapCount == 2) {
appData.mapTargetMaxDist = 0.25 * appData.maxDist;
@ -1104,13 +1106,13 @@ void registerClick() {
//
//
void draw() {
void View::draw() {
uint64_t drawStartTime = mstime();
moveMapToTarget();
zoomMapToTarget();
updatePlanes();
//updatePlanes();
updateStatus();
@ -1157,3 +1159,7 @@ void draw() {
usleep(1000 * (FRAMETIME - (mstime() - drawStartTime)));
}
}
View::View(AircraftData *aircraftData){
this->aircraftData = aircraftData;
}

39
View.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef VIEW_H
#define VIEW_H
#include "AircraftData.h"
class View {
AircraftData *aircraftData;
public:
int screenDist(float d);
void pxFromLonLat(float *dx, float *dy, float lon, float lat);
void latLonFromScreenCoords(float *lat, float *lon, int x, int y);
void screenCoords(int *outX, int *outY, float dx, float dy);
int outOfBounds(int x, int y);
void drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeColor);
void drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor);
void drawTrail(float *oldDx, float *oldDy, float *oldHeading, time_t * oldSeen, int idx);
void drawScaleBars();
void drawPolys(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max);
void drawGeography();
void drawSignalMarks(Aircraft *p, int x, int y);
void drawPlaneText(Aircraft *p);
void drawSelectedAircraftText(Aircraft *p);
void resolveLabelConflicts();
void drawPlanes();
void animateCenterAbsolute(float x, float y);
void moveCenterAbsolute(float x, float y);
void moveCenterRelative(float dx, float dy);
void zoomMapToTarget();
void moveMapToTarget();
void drawMouse();
void registerClick();
void draw();
View(AircraftData *aircraftData);
};
#endif

View file

@ -428,27 +428,27 @@ extern "C" {
// Functions exported from mode_ac.c
//
int detectModeA (uint16_t *m, struct modesMessage *mm);
void decodeModeAMessage(struct modesMessage *mm, int ModeA);
void decodeModeAMessage(Modes *modes, struct modesMessage *mm, int ModeA);
int ModeAToModeC (unsigned int ModeA);
//
// Functions exported from mode_s.c
//
void detectModeS (uint16_t *m, uint32_t mlen);
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
void decodeModesMessage (Modes *modes, struct modesMessage *mm, unsigned char *msg);
void displayModesMessage(struct modesMessage *mm);
void useModesMessage (struct modesMessage *mm);
void useModesMessage (Modes* modes, struct modesMessage *mm);
void computeMagnitudeVector(uint16_t *pData);
int decodeCPR (struct aircraft *a, int fflag, int surface);
int decodeCPRrelative (struct aircraft *a, int fflag, int surface);
void modesInitErrorInfo ();
int decodeCPR (Modes *modes, struct aircraft *a, int fflag, int surface);
int decodeCPRrelative (Modes *modes, struct aircraft *a, int fflag, int surface);
void modesInitErrorInfo (Modes *modes);
//
// Functions exported from interactive.c
//
struct aircraft* interactiveReceiveData(struct modesMessage *mm);
struct aircraft* interactiveReceiveData(Modes *modes, struct modesMessage *mm);
void interactiveShowData(void);
void interactiveRemoveStaleAircrafts(void);
int decodeBinMessage (struct client *c, char *p);
void interactiveRemoveStaleAircrafts(Modes *modes);
int decodeBinMessage (Modes *modes, struct client *c, char *p);
struct aircraft *interactiveFindAircraft(uint32_t addr);
struct stDF *interactiveFindDF (uint32_t addr);
@ -456,10 +456,10 @@ struct stDF *interactiveFindDF (uint32_t addr);
// Functions exported from net_io.c
//
void modesInitNet (void);
void modesReadFromClients (void);
void modesSendAllClients (int service, void *msg, int len);
void modesQueueOutput (struct modesMessage *mm);
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
//void modesReadFromClients (void);
//void modesSendAllClients (int service, void *msg, int len);
//void modesQueueOutput (struct modesMessage *mm);
void modesReadFromClient (Modes *modes, struct client *c, char *sep, int(*handler)(Modes *modes, struct client *, char *));
#ifdef __cplusplus
}

1
init.c
View file

@ -48,7 +48,6 @@ void init(char *title) {
appData.mapTargetLat = 0;
appData.mapTargetMaxDist = 0;
appData.isDragging = 0;
appData.selectedPlane = NULL;
if(appData.fullscreen) {
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.

View file

@ -46,7 +46,7 @@ static uint64_t mstime(void) {
//
// Add a new DF structure to the interactive mode linked list
//
void interactiveCreateDF(struct aircraft *a, struct modesMessage *mm) {
void interactiveCreateDF(Modes *modes, struct aircraft *a, struct modesMessage *mm) {
struct stDF *pDF = (struct stDF *) malloc(sizeof(*pDF));
if (pDF) {
@ -60,60 +60,34 @@ void interactiveCreateDF(struct aircraft *a, struct modesMessage *mm) {
pDF->pAircraft = a;
memcpy(pDF->msg, mm->msg, MODES_LONG_MSG_BYTES);
// if (!pthread_mutex_lock(&modes.pDF_mutex)) {
// if ((pDF->pNext = modes.pDF)) {
// modes.pDF->pPrev = pDF;
// if (!pthread_mutex_lock(&modes->pDF_mutex)) {
// if ((pDF->pNext = modes->pDF)) {
// modes->pDF->pPrev = pDF;
// }
// modes.pDF = pDF;
// pthread_mutex_unlock(&modes.pDF_mutex);
// modes->pDF = pDF;
// pthread_mutex_unlock(&modes->pDF_mutex);
// } else {
// free(pDF);
// }
if ((pDF->pNext = modes.pDF)) {
modes.pDF->pPrev = pDF;
if ((pDF->pNext = modes->pDF)) {
modes->pDF->pPrev = pDF;
}
modes.pDF = pDF;
modes->pDF = pDF;
}
}
//
// Remove stale DF's from the interactive mode linked list
//
void interactiveRemoveStaleDF(time_t now) {
void interactiveRemoveStaleDF( Modes *modes, time_t now) {
struct stDF *pDF = NULL;
struct stDF *prev = NULL;
// Only fiddle with the DF list if we gain possession of the mutex
// If we fail to get the mutex we'll get another chance to tidy the
// DF list in a second or so.
// if (!pthread_mutex_trylock(&modes.pDF_mutex)) {
// pDF = modes.pDF;
// while(pDF) {
// if ((now - pDF->seen) > modes.interactive_delete_ttl) {
// if (modes.pDF == pDF) {
// modes.pDF = NULL;
// } else {
// prev->pNext = NULL;
// }
// // All DF's in the list from here onwards will be time
// // expired, so delete them all
// while (pDF) {
// prev = pDF; pDF = pDF->pNext;
// free(prev);
// }
// } else {
// prev = pDF; pDF = pDF->pNext;
// }
// }
// pthread_mutex_unlock (&modes.pDF_mutex);
// }
pDF = modes.pDF;
pDF = modes->pDF;
while(pDF) {
if ((now - pDF->seen) > modes.interactive_delete_ttl) {
if (modes.pDF == pDF) {
modes.pDF = NULL;
if ((now - pDF->seen) > modes->interactive_delete_ttl) {
if (modes->pDF == pDF) {
modes->pDF = NULL;
} else {
prev->pNext = NULL;
}
@ -131,32 +105,20 @@ void interactiveRemoveStaleDF(time_t now) {
}
}
struct stDF *interactiveFindDF(uint32_t addr) {
struct stDF *pDF = NULL;
// struct stDF *interactiveFindDF(Modes *modes, uint32_t addr) {
// struct stDF *pDF = NULL;
// if (!pthread_mutex_lock(&modes.pDF_mutex)) {
// pDF = modes.pDF;
// pDF = modes->pDF;
// while(pDF) {
// if (pDF->addr == addr) {
// pthread_mutex_unlock (&modes.pDF_mutex);
// return (pDF);
// }
// pDF = pDF->pNext;
// }
// pthread_mutex_unlock (&modes.pDF_mutex);
// return (NULL);
// }
pDF = modes.pDF;
while(pDF) {
if (pDF->addr == addr) {
return (pDF);
}
pDF = pDF->pNext;
}
return (NULL);
}
//
//========================= Interactive mode ===============================
//
@ -196,8 +158,8 @@ struct aircraft *interactiveCreateAircraft(struct modesMessage *mm) {
// Return the aircraft with the specified address, or NULL if no aircraft
// exists with this address.
//
struct aircraft *interactiveFindAircraft(uint32_t addr) {
struct aircraft *a = modes.aircrafts;
struct aircraft *interactiveFindAircraft(Modes *modes, uint32_t addr) {
struct aircraft *a = modes->aircrafts;
while(a) {
if (a->addr == addr) return (a);
@ -205,105 +167,25 @@ struct aircraft *interactiveFindAircraft(uint32_t addr) {
}
return (NULL);
}
//
//=========================================================================
//
// We have received a Mode A or C response.
//
// Search through the list of known Mode-S aircraft and tag them if this Mode A/C
// matches their known Mode S Squawks or Altitudes(+/- 50feet).
//
// A Mode S equipped aircraft may also respond to Mode A and Mode C SSR interrogations.
// We can't tell if this is a Mode A or C, so scan through the entire aircraft list
// looking for matches on Mode A (squawk) and Mode C (altitude). Flag in the Mode S
// records that we have had a potential Mode A or Mode C response from this aircraft.
//
// If an aircraft responds to Mode A then it's highly likely to be responding to mode C
// too, and vice verca. Therefore, once the mode S record is tagged with both a Mode A
// and a Mode C flag, we can be fairly confident that this Mode A/C frame relates to that
// Mode S aircraft.
//
// Mode C's are more likely to clash than Mode A's; There could be several aircraft
// cruising at FL370, but it's less likely (though not impossible) that there are two
// aircraft on the same squawk. Therefore, give precidence to Mode A record matches
//
// Note : It's theoretically possible for an aircraft to have the same value for Mode A
// and Mode C. Therefore we have to check BOTH A AND C for EVERY S.
//
void interactiveUpdateAircraftModeA(struct aircraft *a) {
struct aircraft *b = modes.aircrafts;
while(b) {
if ((b->modeACflags & MODEAC_MSG_FLAG) == 0) {// skip any fudged ICAO records
// If both (a) and (b) have valid squawks...
if ((a->bFlags & b->bFlags) & MODES_ACFLAGS_SQUAWK_VALID) {
// ...check for Mode-A == Mode-S Squawk matches
if (a->modeA == b->modeA) { // If a 'real' Mode-S ICAO exists using this Mode-A Squawk
b->modeAcount = a->messages;
b->modeACflags |= MODEAC_MSG_MODEA_HIT;
a->modeACflags |= MODEAC_MSG_MODEA_HIT;
if ( (b->modeAcount > 0) &&
( (b->modeCcount > 1)
|| (a->modeACflags & MODEAC_MSG_MODEA_ONLY)) ) // Allow Mode-A only matches if this Mode-A is invalid Mode-C
{a->modeACflags |= MODEAC_MSG_MODES_HIT;} // flag this ModeA/C probably belongs to a known Mode S
}
}
// If both (a) and (b) have valid altitudes...
if ((a->bFlags & b->bFlags) & MODES_ACFLAGS_ALTITUDE_VALID) {
// ... check for Mode-C == Mode-S Altitude matches
if ( (a->modeC == b->modeC ) // If a 'real' Mode-S ICAO exists at this Mode-C Altitude
|| (a->modeC == b->modeC + 1) // or this Mode-C - 100 ft
|| (a->modeC + 1 == b->modeC ) ) { // or this Mode-C + 100 ft
b->modeCcount = a->messages;
b->modeACflags |= MODEAC_MSG_MODEC_HIT;
a->modeACflags |= MODEAC_MSG_MODEC_HIT;
if ( (b->modeAcount > 0) &&
(b->modeCcount > 1) )
{a->modeACflags |= (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEC_OLD);} // flag this ModeA/C probably belongs to a known Mode S
}
}
}
b = b->next;
}
}
//
//=========================================================================
//
void interactiveUpdateAircraftModeS() {
struct aircraft *a = modes.aircrafts;
while(a) {
int flags = a->modeACflags;
if (flags & MODEAC_MSG_FLAG) { // find any fudged ICAO records
// clear the current A,C and S hit bits ready for this attempt
a->modeACflags = flags & ~(MODEAC_MSG_MODEA_HIT | MODEAC_MSG_MODEC_HIT | MODEAC_MSG_MODES_HIT);
interactiveUpdateAircraftModeA(a); // and attempt to match them with Mode-S
}
a = a->next;
}
}
//
//=========================================================================
//
// Receive new messages and populate the interactive mode with more info
//
struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
struct aircraft *interactiveReceiveData(Modes *modes, struct modesMessage *mm) {
struct aircraft *a, *aux;
// Return if (checking crc) AND (not crcok) AND (not fixed)
if (modes.check_crc && (mm->crcok == 0) && (mm->correctedbits == 0))
if (modes->check_crc && (mm->crcok == 0) && (mm->correctedbits == 0))
return NULL;
// Lookup our aircraft or create a new one
a = interactiveFindAircraft(mm->addr);
a = interactiveFindAircraft(modes, mm->addr);
if (!a) { // If it's a currently unknown aircraft....
a = interactiveCreateAircraft(mm); // ., create a new record for it,
a->next = modes.aircrafts; // .. and put it at the head of the list
modes.aircrafts = a;
a->next = modes->aircrafts; // .. and put it at the head of the list
modes->aircrafts = a;
} else {
/* If it is an already known aircraft, move it on head
* so we keep aircrafts ordered by received message time.
@ -312,14 +194,14 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
* since the aircraft that is currently on head sent a message,
* othewise with multiple aircrafts at the same time we have an
* useless shuffle of positions on the screen. */
if (0 && modes.aircrafts != a && (time(NULL) - a->seen) >= 1) {
aux = modes.aircrafts;
if (0 && modes->aircrafts != a && (time(NULL) - a->seen) >= 1) {
aux = modes->aircrafts;
while(aux->next != a) aux = aux->next;
/* Now we are a node before the aircraft to remove. */
aux->next = aux->next->next; /* removed. */
/* Add on head */
a->next = modes.aircrafts;
modes.aircrafts = a;
a->next = modes->aircrafts;
modes->aircrafts = a;
}
}
@ -392,13 +274,13 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
// If we have enough recent data, try global CPR
if (((mm->bFlags | a->bFlags) & MODES_ACFLAGS_LLEITHER_VALID) == MODES_ACFLAGS_LLBOTH_VALID && abs((int)(a->even_cprtime - a->odd_cprtime)) <= 10000) {
if (decodeCPR(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) {
if (decodeCPR(modes, a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) {
location_ok = 1;
}
}
// Otherwise try relative CPR.
if (!location_ok && decodeCPRrelative(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) {
if (!location_ok && decodeCPRrelative(modes, a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) {
location_ok = 1;
}
@ -432,8 +314,8 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
}
// If we are Logging DF's, and it's not a Mode A/C
if ((modes.bEnableDFLogging) && (mm->msgtype < 32)) {
interactiveCreateDF(a,mm);
if ((modes->bEnableDFLogging) && (mm->msgtype < 32)) {
interactiveCreateDF(modes,a,mm);
}
return (a);
@ -445,23 +327,23 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
// When in interactive mode If we don't receive new nessages within
// MODES_INTERACTIVE_DELETE_TTL seconds we remove the aircraft from the list.
//
void interactiveRemoveStaleAircrafts(void) {
struct aircraft *a = modes.aircrafts;
void interactiveRemoveStaleAircrafts(Modes *modes) {
struct aircraft *a = modes->aircrafts;
struct aircraft *prev = NULL;
time_t now = time(NULL);
// Only do cleanup once per second
if (modes.last_cleanup_time != now) {
modes.last_cleanup_time = now;
if (modes->last_cleanup_time != now) {
modes->last_cleanup_time = now;
interactiveRemoveStaleDF(now);
interactiveRemoveStaleDF(modes,now);
while(a) {
if ((now - a->seen) > modes.interactive_delete_ttl) {
if ((now - a->seen) > modes->interactive_delete_ttl) {
// Remove the element from the linked list, with care
// if we are removing the first element
if (!prev) {
modes.aircrafts = a->next; free(a); a = modes.aircrafts;
modes->aircrafts = a->next; free(a); a = modes->aircrafts;
} else {
prev->next = a->next; free(a); a = prev->next;
}

152
map1090.cpp Normal file
View file

@ -0,0 +1,152 @@
// view1090, a Mode S messages viewer for dump1090 devices.
//
// Copyright (C) 2014 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"
#include "structs.h"
#include "AircraftData.h"
#include "View.h"
#include "Input.h"
//time utility, might change to std::chrono
uint64_t mstime(void) {
struct timeval tv;
uint64_t mst;
gettimeofday(&tv, NULL);
mst = ((uint64_t)tv.tv_sec)*1000;
mst += tv.tv_usec/1000;
return mst;
}
int go = 1;
AppData appData;
Style style;
//
// ================================ Main ====================================
//
void showHelp(void) {
printf(
"-----------------------------------------------------------------------------\n"
"| view1090 dump1090 Viewer Ver : " MODES_DUMP1090_VERSION " |\n"
"-----------------------------------------------------------------------------\n"
"--server <IPv4/hosname> TCP Beast output listen IPv4 (default: 127.0.0.1)\n"
"--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"
"--metric Use metric units (meters, km/h, ...)\n"
"--help Show this help\n"
"--uiscale <factor> UI global scaling (default: 1)\n"
"--screensize <width> <height> Set frame buffer resolution (default: screen resolution)\n"
"--fullscreen Start fullscreen\n"
);
}
//
//=========================================================================
//
int main(int argc, char **argv) {
int j;
AircraftData aircraftData;
View view(&aircraftData);
Input input(&view);
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
aircraftData.initialize();
// 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) {
aircraftData.modes.net_input_beast_port = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--port") && more) {
aircraftData.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],"--server") && more) {
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
} else if (!strcmp(argv[j],"--lat") && more) {
aircraftData.modes.fUserLat = atof(argv[++j]);
appData.centerLat = aircraftData.modes.fUserLat;
} else if (!strcmp(argv[j],"--lon") && more) {
aircraftData.modes.fUserLon = atof(argv[++j]);
appData.centerLon = aircraftData.modes.fUserLon;
} else if (!strcmp(argv[j],"--metric")) {
aircraftData.modes.metric = 1;
} else if (!strcmp(argv[j],"--fullscreen")) {
appData.fullscreen = 1;
} else if (!strcmp(argv[j],"--uiscale") && more) {
appData.screen_uiscale = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--screensize") && more) {
appData.screen_width = atoi(argv[++j]);
appData.screen_height = atoi(argv[++j]);
} 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);
}
}
int go;
aircraftData.connect();
init("sdl1090");
atexit(cleanup);
go = 1;
while (go == 1)
{
input.getInput();
aircraftData.update();
view.draw();
}
aircraftData.disconnect();
return (0);
}
//
//=========================================================================
//

1162
mode_s.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
aaf101fcf91be4f20921260cd579f3fa5dda321e

250
net_io.c
View file

@ -55,102 +55,18 @@ struct service {
struct service services[MODES_NET_SERVICES_NUM];
void modesInitNet(void) {
int j;
struct service svc[MODES_NET_SERVICES_NUM] = {
{"Raw TCP output", &modes.ros, modes.net_output_raw_port, 1},
{"Raw TCP input", &modes.ris, modes.net_input_raw_port, 1},
{"Beast TCP output", &modes.bos, modes.net_output_beast_port, 1},
{"Beast TCP input", &modes.bis, modes.net_input_beast_port, 1},
{"HTTP server", &modes.https, modes.net_http_port, 1},
{"Basestation TCP output", &modes.sbsos, modes.net_output_sbs_port, 1}
};
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++) {
services[j].enabled = (services[j].port != 0);
if (services[j].enabled) {
int s = anetTcpServer(modes.aneterr, services[j].port, modes.net_bind_address);
if (s == -1) {
fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
services[j].port, services[j].descr, modes.aneterr);
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
}
//
//=========================================================================
//
// This function gets called from time to time when the decoding thread is
// awakened by new data arriving. This usually happens a few times every second
//
struct client * modesAcceptClients(void) {
int fd, port;
unsigned int j;
struct client *c;
for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
if (services[j].enabled) {
fd = anetTcpAccept(modes.aneterr, *services[j].socket, NULL, &port);
if (fd == -1) continue;
anetNonBlock(modes.aneterr, fd);
c = (struct client *) malloc(sizeof(*c));
c->service = *services[j].socket;
c->next = modes.clients;
c->fd = fd;
c->buflen = 0;
modes.clients = c;
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.ros) modes.stat_raw_connections++;
if (*services[j].socket == modes.bos) modes.stat_beast_connections++;
j--; // Try again with the same listening port
if (modes.debug & MODES_DEBUG_NET)
printf("Created new client %d\n", fd);
}
}
return modes.clients;
}
//
//=========================================================================
//
// On error free the client, collect the structure, adjust maxfd if needed.
//
void modesFreeClient(struct client *c) {
void modesFreeClient(Modes * modes, struct client *c) {
// Unhook this client from the linked list of clients
struct client *p = modes.clients;
struct client *p = modes->clients;
if (p) {
if (p == c) {
modes.clients = c->next;
modes->clients = c->next;
} else {
while ((p) && (p->next != c)) {
p = p->next;
@ -168,17 +84,17 @@ void modesFreeClient(struct client *c) {
//
// Close the client connection and mark it as closed
//
void modesCloseClient(struct client *c) {
void modesCloseClient(Modes *modes, struct client *c) {
close(c->fd);
if (c->service == modes.sbsos) {
if (modes.stat_sbs_connections) modes.stat_sbs_connections--;
} else if (c->service == modes.ros) {
if (modes.stat_raw_connections) modes.stat_raw_connections--;
} else if (c->service == modes.bos) {
if (modes.stat_beast_connections) modes.stat_beast_connections--;
if (c->service == modes->sbsos) {
if (modes->stat_sbs_connections) modes->stat_sbs_connections--;
} else if (c->service == modes->ros) {
if (modes->stat_raw_connections) modes->stat_raw_connections--;
} else if (c->service == modes->bos) {
if (modes->stat_beast_connections) modes->stat_beast_connections--;
}
if (modes.debug & MODES_DEBUG_NET)
if (modes->debug & MODES_DEBUG_NET)
printf("Closing client %d\n", c->fd);
c->fd = -1;
@ -196,7 +112,7 @@ void modesCloseClient(struct client *c) {
// The function always returns 0 (success) to the caller as there is no
// case where we want broken messages here to close the client connection.
//
int decodeBinMessage(struct client *c, char *p) {
int decodeBinMessage(Modes *modes, struct client *c, char *p) {
int msgLen = 0;
int j;
char ch;
@ -209,7 +125,7 @@ int decodeBinMessage(struct client *c, char *p) {
ch = *p++; /// Get the message type
if (0x1A == ch) {p++;}
if ((ch == '1') && (modes.mode_ac)) { // skip ModeA/C unless user enables --modes-ac
if ((ch == '1') && (modes->mode_ac)) { // skip ModeA/C unless user enables --modes-ac
msgLen = MODEAC_MSG_BYTES;
} else if (ch == '2') {
msgLen = MODES_SHORT_MSG_BYTES;
@ -236,13 +152,13 @@ int decodeBinMessage(struct client *c, char *p) {
if (0x1A == ch) {p++;}
}
if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
} else {
decodeModesMessage(&mm, msg);
}
// if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
// decodeModeAMessage(modes, &mm, ((msg[0] << 8) | msg[1]));
// } else {
decodeModesMessage(modes, &mm, msg);
//}
useModesMessage(&mm);
useModesMessage(modes, &mm);
}
return (0);
}
@ -259,91 +175,6 @@ int hexDigitVal(int c) {
else return -1;
}
//
//=========================================================================
//
// This function decodes a string representing message in raw hex format
// like: *8D4B969699155600E87406F5B69F; The string is null-terminated.
//
// The message is passed to the higher level layers, so it feeds
// the selected screen output, the network output and so forth.
//
// If the message looks invalid it is silently discarded.
//
// The function always returns 0 (success) to the caller as there is no
// case where we want broken messages here to close the client connection.
//
int decodeHexMessage(struct client *c, char *hex) {
int l = strlen(hex), j;
unsigned char msg[MODES_LONG_MSG_BYTES];
struct modesMessage mm;
MODES_NOTUSED(c);
memset(&mm, 0, sizeof(mm));
// 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
mm.remote = 1;
mm.signalLevel = 0xFF;
// Remove spaces on the left and on the right
while(l && isspace(hex[l-1])) {
hex[l-1] = '\0'; l--;
}
while(isspace(*hex)) {
hex++; l--;
}
// Turn the message into binary.
// Accept *-AVR raw @-AVR/BEAST timeS+raw %-AVR timeS+raw (CRC good) <-BEAST timeS+sigL+raw
// and some AVR records that we can understand
if (hex[l-1] != ';') {return (0);} // not complete - abort
switch(hex[0]) {
case '<': {
mm.signalLevel = (hexDigitVal(hex[13])<<4) | hexDigitVal(hex[14]);
hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ;
break;}
case '@': // No CRC check
case '%': { // CRC is OK
hex += 13; l -= 14; // Skip @,%, and timestamp, and ;
break;}
case '*':
case ':': {
hex++; l-=2; // Skip * and ;
break;}
default: {
return (0); // We don't know what this is, so abort
break;}
}
if ( (l != (MODEAC_MSG_BYTES * 2))
&& (l != (MODES_SHORT_MSG_BYTES * 2))
&& (l != (MODES_LONG_MSG_BYTES * 2)) )
{return (0);} // Too short or long message... broken
if ( (0 == modes.mode_ac)
&& (l == (MODEAC_MSG_BYTES * 2)) )
{return (0);} // Right length for ModeA/C, but not enabled
for (j = 0; j < l; j += 2) {
int high = hexDigitVal(hex[j]);
int low = hexDigitVal(hex[j+1]);
if (high == -1 || low == -1) return 0;
msg[j/2] = (high << 4) | low;
}
if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC
decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
} else { // Assume ModeS
decodeModesMessage(&mm, msg);
}
useModesMessage(&mm);
return (0);
}
//
//=========================================================================
//
@ -359,8 +190,8 @@ int decodeHexMessage(struct client *c, char *hex) {
// The handler returns 0 on success, or 1 to signal this function we should
// close the connection with the client in case of non-recoverable errors.
//
void modesReadFromClient(struct client *c, char *sep,
int(*handler)(struct client *, char *)) {
void modesReadFromClient(Modes *modes, struct client *c, char *sep,
int(*handler)(Modes *modes, struct client *, char *)) {
int left;
int nread;
int fullmsg;
@ -384,7 +215,7 @@ void modesReadFromClient(struct client *c, char *sep,
if (nread < 0) {errno = WSAGetLastError();}
#endif
if (nread == 0) {
modesCloseClient(c);
modesCloseClient(modes, c);
return;
}
@ -397,7 +228,7 @@ void modesReadFromClient(struct client *c, char *sep,
#else
if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file
#endif
modesCloseClient(c);
modesCloseClient(modes, c);
return;
}
if (nread <= 0) {
@ -412,7 +243,7 @@ void modesReadFromClient(struct client *c, char *sep,
if (c->service == modes.bis) {
if (c->service == modes->bis) {
// This is the Beast Binary scanning case.
// If there is a complete message still in the buffer, there must be the separator 'sep'
// in the buffer, note that we full-scan the buffer at every read for simplicity.
@ -446,8 +277,8 @@ void modesReadFromClient(struct client *c, char *sep,
break;
}
// Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
if (handler(c, s)) {
modesCloseClient(c);
if (handler(modes, c, s)) {
modesCloseClient(modes, c);
return;
}
fullmsg = 1;
@ -462,8 +293,8 @@ void modesReadFromClient(struct client *c, char *sep,
//
while ((e = strstr(s, sep)) != NULL) { // end of first message if found
*e = '\0'; // The handler expects null terminated strings
if (handler(c, s)) { // Pass message to handler.
modesCloseClient(c); // Handler returns 1 on error to signal we .
if (handler(modes, c, s)) { // Pass message to handler.
modesCloseClient(modes, c); // Handler returns 1 on error to signal we .
return; // should close the client connection
}
s = e + strlen(sep); // Move to start of next message
@ -479,28 +310,3 @@ void modesReadFromClient(struct client *c, char *sep,
}
}
}
//
//=========================================================================
//
// Read data from clients. This function actually delegates a lower-level
// function that depends on the kind of service (raw, http, ...).
//
void modesReadFromClients(void) {
struct client *c = modesAcceptClients();
while (c) {
// Read next before servicing client incase the service routine deletes the client!
struct client *next = c->next;
if (c->fd >= 0) {
modesReadFromClient(c,"",decodeBinMessage);
} else {
modesFreeClient(c);
}
c = next;
}
}
//
// =============================== Network IO ===========================
//

View file

@ -13,66 +13,26 @@ void updateStatus() {
double sigAccumulate = 0.0;
double msgRateAccumulate = 0.0;
/*
while(a) {
int flags = a->modeACflags;
int msgs = a->messages;
if ( (((flags & (MODEAC_MSG_FLAG )) == 0 ) )
|| (((flags & (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEA_ONLY)) == MODEAC_MSG_MODEA_ONLY) && (msgs > 4 ) )
|| (((flags & (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEC_OLD )) == 0 ) && (msgs > 127) )
) {
// PlaneObj *p = appData.planes;
unsigned char * pSig = a->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7]);
// while(p) {
// unsigned char * pSig = p->signalLevel;
// unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
// pSig[4] + pSig[5] + pSig[6] + pSig[7]);
sigAccumulate += signalAverage;
// sigAccumulate += signalAverage;
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
double d = sqrt(a->dx * a->dx + a->dy * a->dy);
// if (p->lon && p->lat) {
// numVisiblePlanes++;
// }
if(d < appData.maxDist) {
if(d > maxDist) {
maxDist = d;
}
// totalCount++;
if(d < 4.0) {
Status.closeCall = a;
}
// msgRateAccumulate += p->messageRate;
numVisiblePlanes++;
}
}
totalCount++;
}
msgRateAccumulate += (a->messageRate[0] + a->messageRate[1] + a->messageRate[2] + a->messageRate[3] +
a->messageRate[4] + a->messageRate[5] + a->messageRate[6] + a->messageRate[7]);
a = a->next;
}
*/
PlaneObj *p = appData.planes;
while(p) {
unsigned char * pSig = p->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7]);
sigAccumulate += signalAverage;
if (p->lon && p->lat) {
numVisiblePlanes++;
}
totalCount++;
msgRateAccumulate += p->messageRate;
p = p->next;
}
// p = p->next;
// }
Status.msgRate = msgRateAccumulate;
Status.avgSig = sigAccumulate / (double) totalCount;

View file

@ -3,42 +3,7 @@
#include "defs.h"
// mirrors aircraft struct in dump1090, separating for refactoring
typedef struct PlaneObj {
uint32_t addr; // ICAO address
char flight[16]; // Flight number
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
double messageRate;
int altitude; // Altitude
int speed; // Velocity
int track; // Angle of flight
int vert_rate; // Vertical rate.
time_t seen; // Time at which the last packet was received
time_t seenLatLon; // Time at which the last packet was received
time_t prev_seen;
double lat, lon; // Coordinated obtained from CPR encoded data
//history
float oldLon[TRAIL_LENGTH];
float oldLat[TRAIL_LENGTH];
float oldHeading[TRAIL_LENGTH];
time_t oldSeen[TRAIL_LENGTH];
uint8_t oldIdx;
uint64_t created;
uint64_t msSeen;
uint64_t msSeenLatLon;
int live;
struct PlaneObj *next; // Next aircraft in our linked list
//// label stuff
int x, y, cx, cy, w, h;
float ox, oy, dox, doy, ddox, ddoy;
float pressure;
} PlaneObj;
#include "AircraftData.h"
typedef struct AppData
@ -93,8 +58,8 @@ typedef struct AppData
QuadTree root;
PlaneObj *planes;
PlaneObj *selectedPlane;
//PlaneObj *planes;
//PlaneObj *selectedPlane;
uint64_t lastFrameTime;
} AppData;
@ -142,28 +107,17 @@ void drawStringBG(char *, int, int, TTF_Font *, SDL_Color, SDL_Color);
void init(char *);
void cleanup(void);
//input.c
void getInput(void);
//mapdata.c
void initMaps();
//list.c
void drawList(int top);
//draw.c
void draw();
void latLonFromScreenCoords(float *lat, float *lon, int x, int y);
void moveCenterAbsolute(float x, float y);
void moveCenterRelative(float dx, float dy);
void registerClick();
//status.c
void updateStatus();
void drawStatus();
//planeObj.c
void updatePlanes();
#ifdef __cplusplus
}
#endif

View file

@ -30,6 +30,7 @@
#include "view1090.h"
#include "structs.h"
#include "AircraftData.h"
int go = 1;
@ -37,117 +38,26 @@ int go = 1;
AppData appData;
Style style;
Modes modes;
//
// ============================= 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
AircraftData.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 = 0;
modes.quiet = 1;
// Map options
appData.maxDist = 25.0;
appData.centerLon = modes.fUserLon;
appData.centerLat = modes.fUserLat;
// Display options
appData.screen_uiscale = 1;
appData.screen_width = 0;
appData.screen_height = 0;
appData.screen_depth = 32;
appData.fullscreen = 0;
// Initialize status
Status.msgRate = 0;
Status.avgSig = 0;
Status.numPlanes = 0;
Status.numVisiblePlanes = 0;
Status.maxDist = 0;
}
//
//=========================================================================
//
void view1090Init(void) {
// pthread_mutex_init(&modes.pDF_mutex,NULL);
// pthread_mutex_init(&modes.data_mutex,NULL);
// pthread_cond_init(&modes.data_cond,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
// 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();
}
// Set up data connection
int setupConnection(struct client *c) {
int fd;
// 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) {
anetNonBlock(modes.aneterr, fd);
if ((fd = anetTcpConnect(AircraftData.modes.aneterr, View1090.net_input_beast_ipaddr, AircraftData.modes.net_input_beast_port)) != ANET_ERR) {
anetNonBlock(AircraftData.modes.aneterr, fd);
//
// 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
@ -163,8 +73,8 @@ int setupConnection(struct client *c) {
c->buflen = 0;
c->fd =
c->service =
modes.bis = fd;
modes.clients = c;
AircraftData.modes.bis = fd;
AircraftData.modes.clients = c;
}
return fd;
}
@ -232,31 +142,33 @@ int main(int argc, char **argv) {
struct client *c;
char pk_buf[8];
// Set sane defaults
AircraftData aircraftData;
view1090InitConfig();
signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)
aircraftData.initialize();
// 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]);
AircraftData.modes.net_input_beast_port = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--port") && more) {
modes.net_input_beast_port = atoi(argv[++j]);
AircraftData.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],"--server") && more) {
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
} else if (!strcmp(argv[j],"--lat") && more) {
modes.fUserLat = atof(argv[++j]);
appData.centerLat = modes.fUserLat;
AircraftData.modes.fUserLat = atof(argv[++j]);
appData.centerLat = AircraftData.modes.fUserLat;
} else if (!strcmp(argv[j],"--lon") && more) {
modes.fUserLon = atof(argv[++j]);
appData.centerLon = modes.fUserLon;
AircraftData.modes.fUserLon = atof(argv[++j]);
appData.centerLon = AircraftData.modes.fUserLon;
} else if (!strcmp(argv[j],"--metric")) {
modes.metric = 1;
AircraftData.modes.metric = 1;
} else if (!strcmp(argv[j],"--fullscreen")) {
appData.fullscreen = 1;
} else if (!strcmp(argv[j],"--uiscale") && more) {
@ -274,14 +186,11 @@ int main(int argc, char **argv) {
}
}
// Initialization
view1090Init();
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
c = (struct client *) malloc(sizeof(*c));
while(1) {
if ((fd = setupConnection(c)) == ANET_ERR) {
fprintf(stderr, "Waiting on %s:%d\n", View1090.net_input_beast_ipaddr, modes.net_input_beast_port);
fprintf(stderr, "Waiting on %s:%d\n", View1090.net_input_beast_ipaddr, AircraftData.modes.net_input_beast_port);
sleep(1);
} else {
break;