massive refactor to c++ in progress, doesn't build now
Former-commit-id: bbd3fe3c0438b9f8d2188b8d1f5ffc70616a789f Former-commit-id: d19da520563adeb80996df92c65ba5e1e6785596
This commit is contained in:
parent
cb62238efd
commit
af9cfce3ff
33
Aircraft.cpp
Normal file
33
Aircraft.cpp
Normal 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
43
Aircraft.h
Normal 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
131
AircraftData.cpp
Normal 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
34
AircraftData.h
Normal 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
|
|
@ -1,4 +1,4 @@
|
||||||
#include "structs.h"
|
#include "AircraftList.h"
|
||||||
#include "dump1090.h"
|
#include "dump1090.h"
|
||||||
|
|
||||||
static uint64_t mstime(void) {
|
static uint64_t mstime(void) {
|
||||||
|
@ -11,8 +11,8 @@ static uint64_t mstime(void) {
|
||||||
return mst;
|
return mst;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaneObj *findPlaneObj(uint32_t addr) {
|
Aircraft *AircraftList::find(uint32_t addr) {
|
||||||
PlaneObj *p = appData.planes;
|
Aircraft *p = head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
if (p->addr == addr) return (p);
|
if (p->addr == addr) return (p);
|
||||||
|
@ -21,39 +21,12 @@ PlaneObj *findPlaneObj(uint32_t addr) {
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaneObj *createPlaneObj(struct aircraft *a) {
|
void AircraftList::update
|
||||||
PlaneObj *p = (PlaneObj *) malloc(sizeof(*p));
|
() {
|
||||||
|
//instead of this, net_io should call this class directly to update info
|
||||||
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() {
|
|
||||||
struct aircraft *a = modes.aircrafts;
|
struct aircraft *a = modes.aircrafts;
|
||||||
|
|
||||||
PlaneObj *p = appData.planes;
|
Aircraft *p = head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
p->live = 0;
|
p->live = 0;
|
||||||
|
@ -62,11 +35,12 @@ void updatePlanes() {
|
||||||
|
|
||||||
while(a) {
|
while(a) {
|
||||||
|
|
||||||
p = findPlaneObj(a->addr);
|
p = find(a->addr);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = createPlaneObj(a);
|
//p = createPlaneObj(a);
|
||||||
p->next = appData.planes;
|
p = new Aircraft(a);
|
||||||
appData.planes = p;
|
p->next = head;
|
||||||
|
head = p;
|
||||||
} else {
|
} else {
|
||||||
p->prev_seen = p->seen;
|
p->prev_seen = p->seen;
|
||||||
}
|
}
|
||||||
|
@ -113,18 +87,18 @@ void updatePlanes() {
|
||||||
a = a->next;
|
a = a->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = appData.planes;
|
p = head;
|
||||||
PlaneObj *prev = NULL;
|
Aircraft *prev = NULL;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
if(!p->live) {
|
if(!p->live) {
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
appData.planes = p->next;
|
head = p->next;
|
||||||
free(p);
|
delete(p);
|
||||||
p = appData.planes;
|
p = head;
|
||||||
} else {
|
} else {
|
||||||
prev->next = p->next;
|
prev->next = p->next;
|
||||||
free(p);
|
delete(p);
|
||||||
p = prev->next;
|
p = prev->next;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
12
AircraftList.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include "Aircraft.h"
|
||||||
|
|
||||||
|
class AircraftList {
|
||||||
|
public:
|
||||||
|
Aircraft *head;
|
||||||
|
|
||||||
|
Aircraft *find(uint32_t addr);
|
||||||
|
void update();
|
||||||
|
|
||||||
|
AircraftList();
|
||||||
|
~AircraftList();
|
||||||
|
};
|
|
@ -1,6 +1,8 @@
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "view1090.h"
|
#include "view1090.h"
|
||||||
|
|
||||||
|
#include "Input.h"
|
||||||
|
|
||||||
static uint64_t mstime(void) {
|
static uint64_t mstime(void) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
uint64_t mst;
|
uint64_t mst;
|
||||||
|
@ -11,7 +13,7 @@ static uint64_t mstime(void) {
|
||||||
return mst;
|
return mst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getInput()
|
void Input::getInput()
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ void getInput()
|
||||||
appData.touchy = event.motion.y;
|
appData.touchy = event.motion.y;
|
||||||
appData.tapCount = event.button.clicks;
|
appData.tapCount = event.button.clicks;
|
||||||
|
|
||||||
registerClick();
|
view->registerClick();
|
||||||
|
|
||||||
appData.isDragging = 0;
|
appData.isDragging = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -72,9 +74,13 @@ void getInput()
|
||||||
|
|
||||||
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) {
|
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) {
|
||||||
appData.isDragging = 1;
|
appData.isDragging = 1;
|
||||||
moveCenterRelative(event.motion.xrel, event.motion.yrel);
|
view->moveCenterRelative(event.motion.xrel, event.motion.yrel);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Input::Input(View *view) {
|
||||||
|
this->view = view;
|
||||||
|
}
|
17
Input.h
Normal file
17
Input.h
Normal 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
|
11
Makefile
11
Makefile
|
@ -2,19 +2,18 @@
|
||||||
# When building a package or installing otherwise in the system, make
|
# When building a package or installing otherwise in the system, make
|
||||||
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
||||||
#
|
#
|
||||||
PROGNAME=view1090
|
|
||||||
|
|
||||||
CFLAGS=-O2 -g -Wall -W
|
CFLAGS=-O2 -g -Wall -W
|
||||||
LIBS=-lm -lSDL2 -lSDL2_ttf -lSDL2_gfx
|
LIBS=-lm -lSDL2 -lSDL2_ttf -lSDL2_gfx
|
||||||
CC=g++
|
CC=g++
|
||||||
|
|
||||||
all: view1090
|
all: map1090
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c %.cpp
|
||||||
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
|
$(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
|
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 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)
|
$(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:
|
clean:
|
||||||
rm -f *.o view1090
|
rm -f *.o map1090
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "parula.h"
|
#include "parula.h"
|
||||||
#include "monokai.h"
|
#include "monokai.h"
|
||||||
|
|
||||||
|
#include "View.h"
|
||||||
|
|
||||||
static uint64_t mstime(void) {
|
static uint64_t mstime(void) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
uint64_t mst;
|
uint64_t mst;
|
||||||
|
@ -17,11 +19,11 @@ static uint64_t mstime(void) {
|
||||||
return mst;
|
return mst;
|
||||||
}
|
}
|
||||||
|
|
||||||
float sign(float x) {
|
static float sign(float x) {
|
||||||
return (x > 0) - (x < 0);
|
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;
|
float out = in;
|
||||||
|
|
||||||
if(in < min) {
|
if(in < min) {
|
||||||
|
@ -35,7 +37,7 @@ float clamp(float in, float min, float max) {
|
||||||
return out;
|
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[0] = u[1]*w[2] - u[2]*(w)[1];
|
||||||
v[1] = u[2]*w[0] - u[0]*(w)[2];
|
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;
|
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;
|
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);
|
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;
|
*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 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 );
|
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);
|
*outX = (appData.screen_width>>1) + ((dx>0) ? 1 : -1) * screenDist(dx);
|
||||||
*outY = (appData.screen_height * CENTEROFFSET) + ((dy>0) ? -1 : 1) * screenDist(dy);
|
*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 ) {
|
if(x < 0 || x >= appData.screen_width || y < 0 || y >= appData.screen_height ) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} 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;
|
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;
|
*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 body = 8.0 * appData.screen_uiscale;
|
||||||
float wing = 6.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);
|
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;
|
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 scalePower = 0;
|
||||||
int scaleBarDist = screenDist((float)pow(10,scalePower));
|
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);
|
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) {
|
if(tree == NULL) {
|
||||||
return;
|
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;
|
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);
|
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);
|
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 char * pSig = p->signalLevel;
|
||||||
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
||||||
pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 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 maxCharCount = 0;
|
||||||
int currentCharCount;
|
int currentCharCount;
|
||||||
|
|
||||||
|
@ -599,7 +601,7 @@ void drawPlaneText(PlaneObj *p) {
|
||||||
p->h = currentLine * appData.mapFontHeight;
|
p->h = currentLine * appData.mapFontHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawSelectedPlaneText(PlaneObj *p) {
|
void View::drawSelectedAircraftText(Aircraft *p) {
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -653,12 +655,12 @@ void drawSelectedPlaneText(PlaneObj *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolveLabelConflicts() {
|
void View::resolveLabelConflicts() {
|
||||||
PlaneObj *p = appData.planes;
|
Aircraft *p = aircraftData->aircraftList.head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
|
|
||||||
PlaneObj *check_p = appData.planes;
|
Aircraft *check_p = aircraftData->aircraftList.head;
|
||||||
|
|
||||||
int p_left = p->x - 10 * appData.screen_uiscale;
|
int p_left = p->x - 10 * appData.screen_uiscale;
|
||||||
int p_right = p->x + p->w + 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 = check_p -> next;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_p = appData.planes;
|
check_p = aircraftData->aircraftList.head;
|
||||||
|
|
||||||
//check against plane icons (include self)
|
//check against plane icons (include self)
|
||||||
|
|
||||||
|
@ -803,7 +805,7 @@ void resolveLabelConflicts() {
|
||||||
|
|
||||||
//update
|
//update
|
||||||
|
|
||||||
p = appData.planes;
|
p = aircraftData->aircraftList.head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
//incorporate acceleration from label conflict resolution
|
//incorporate acceleration from label conflict resolution
|
||||||
|
@ -843,8 +845,8 @@ void resolveLabelConflicts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void drawPlanes() {
|
void View::drawPlanes() {
|
||||||
PlaneObj *p = appData.planes;
|
Aircraft *p = aircraftData->aircraftList.head;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
SDL_Color planeColor;
|
SDL_Color planeColor;
|
||||||
|
|
||||||
|
@ -858,12 +860,12 @@ void drawPlanes() {
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(appData.selectedPlane) {
|
if(aircraftData->selectedAircraft) {
|
||||||
appData.mapTargetLon = appData.selectedPlane->lon;
|
appData.mapTargetLon = aircraftData->selectedAircraft->lon;
|
||||||
appData.mapTargetLat = appData.selectedPlane->lat;
|
appData.mapTargetLat = aircraftData->selectedAircraft->lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = appData.planes;
|
p = aircraftData->aircraftList.head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
if ((now - p->seen) < modes.interactive_display_ttl) {
|
if ((now - p->seen) < modes.interactive_display_ttl) {
|
||||||
|
@ -900,7 +902,7 @@ void drawPlanes() {
|
||||||
usey = y + (mstime() - p->msSeenLatLon) * vely;
|
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?
|
// this logic should be in input, register a callback for click?
|
||||||
float elapsed = mstime() - appData.touchDownTime;
|
float elapsed = mstime() - appData.touchDownTime;
|
||||||
|
|
||||||
|
@ -935,7 +937,7 @@ void drawPlanes() {
|
||||||
p->cy = usey;
|
p->cy = usey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p != appData.selectedPlane) {
|
if(p != aircraftData->selectedAircraft) {
|
||||||
drawPlaneText(p);
|
drawPlaneText(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,7 +948,7 @@ void drawPlanes() {
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSelectedPlaneText(appData.selectedPlane);
|
drawSelectedAircraftText(aircraftData->selectedAircraft);
|
||||||
|
|
||||||
if(appData.touchx && appData.touchy) {
|
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 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);
|
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 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);
|
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;
|
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
|
// 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;
|
appData.mapMoved = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoomMapToTarget() {
|
void View::zoomMapToTarget() {
|
||||||
if(appData.mapTargetMaxDist) {
|
if(appData.mapTargetMaxDist) {
|
||||||
if(fabs(appData.mapTargetMaxDist - appData.maxDist) > 0.0001) {
|
if(fabs(appData.mapTargetMaxDist - appData.maxDist) > 0.0001) {
|
||||||
appData.maxDist += 0.1 * (appData.mapTargetMaxDist - appData.maxDist);
|
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(appData.mapTargetLon && appData.mapTargetLat) {
|
||||||
if(fabs(appData.mapTargetLon - appData.centerLon) > 0.0001 || fabs(appData.mapTargetLat - appData.centerLat) > 0.0001) {
|
if(fabs(appData.mapTargetLon - appData.centerLon) > 0.0001 || fabs(appData.mapTargetLat - appData.centerLat) > 0.0001) {
|
||||||
appData.centerLon += 0.1 * (appData.mapTargetLon- appData.centerLon);
|
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) {
|
if(appData.mouseMovedTime == 0 || (mstime() - appData.mouseMovedTime) > 1000) {
|
||||||
appData.mouseMovedTime = 0;
|
appData.mouseMovedTime = 0;
|
||||||
return;
|
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);
|
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) {
|
if(appData.tapCount == 1 && appData.isDragging == 0) {
|
||||||
PlaneObj *p = appData.planes;
|
Aircraft *p = aircraftData->aircraftList.head;
|
||||||
PlaneObj *selection = NULL;
|
Aircraft *selection = NULL;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
if(appData.touchx && appData.touchy) {
|
if(appData.touchx && appData.touchy) {
|
||||||
|
@ -1091,8 +1093,8 @@ void registerClick() {
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(appData.selectedPlane == NULL) {
|
//if(aircraftData->selectedAircraft == NULL) {
|
||||||
appData.selectedPlane = selection;
|
aircraftData->selectedAircraft = selection;
|
||||||
//}
|
//}
|
||||||
} else if(appData.tapCount == 2) {
|
} else if(appData.tapCount == 2) {
|
||||||
appData.mapTargetMaxDist = 0.25 * appData.maxDist;
|
appData.mapTargetMaxDist = 0.25 * appData.maxDist;
|
||||||
|
@ -1104,13 +1106,13 @@ void registerClick() {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
void draw() {
|
void View::draw() {
|
||||||
uint64_t drawStartTime = mstime();
|
uint64_t drawStartTime = mstime();
|
||||||
|
|
||||||
moveMapToTarget();
|
moveMapToTarget();
|
||||||
zoomMapToTarget();
|
zoomMapToTarget();
|
||||||
|
|
||||||
updatePlanes();
|
//updatePlanes();
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
|
||||||
|
@ -1157,3 +1159,7 @@ void draw() {
|
||||||
usleep(1000 * (FRAMETIME - (mstime() - drawStartTime)));
|
usleep(1000 * (FRAMETIME - (mstime() - drawStartTime)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
View::View(AircraftData *aircraftData){
|
||||||
|
this->aircraftData = aircraftData;
|
||||||
|
}
|
39
View.h
Normal file
39
View.h
Normal 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
|
26
dump1090.h
26
dump1090.h
|
@ -428,27 +428,27 @@ extern "C" {
|
||||||
// Functions exported from mode_ac.c
|
// Functions exported from mode_ac.c
|
||||||
//
|
//
|
||||||
int detectModeA (uint16_t *m, struct modesMessage *mm);
|
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);
|
int ModeAToModeC (unsigned int ModeA);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Functions exported from mode_s.c
|
// Functions exported from mode_s.c
|
||||||
//
|
//
|
||||||
void detectModeS (uint16_t *m, uint32_t mlen);
|
void detectModeS (uint16_t *m, uint32_t mlen);
|
||||||
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
|
void decodeModesMessage (Modes *modes, struct modesMessage *mm, unsigned char *msg);
|
||||||
void displayModesMessage(struct modesMessage *mm);
|
void displayModesMessage(struct modesMessage *mm);
|
||||||
void useModesMessage (struct modesMessage *mm);
|
void useModesMessage (Modes* modes, struct modesMessage *mm);
|
||||||
void computeMagnitudeVector(uint16_t *pData);
|
void computeMagnitudeVector(uint16_t *pData);
|
||||||
int decodeCPR (struct aircraft *a, int fflag, int surface);
|
int decodeCPR (Modes *modes, struct aircraft *a, int fflag, int surface);
|
||||||
int decodeCPRrelative (struct aircraft *a, int fflag, int surface);
|
int decodeCPRrelative (Modes *modes, struct aircraft *a, int fflag, int surface);
|
||||||
void modesInitErrorInfo ();
|
void modesInitErrorInfo (Modes *modes);
|
||||||
//
|
//
|
||||||
// Functions exported from interactive.c
|
// Functions exported from interactive.c
|
||||||
//
|
//
|
||||||
struct aircraft* interactiveReceiveData(struct modesMessage *mm);
|
struct aircraft* interactiveReceiveData(Modes *modes, struct modesMessage *mm);
|
||||||
void interactiveShowData(void);
|
void interactiveShowData(void);
|
||||||
void interactiveRemoveStaleAircrafts(void);
|
void interactiveRemoveStaleAircrafts(Modes *modes);
|
||||||
int decodeBinMessage (struct client *c, char *p);
|
int decodeBinMessage (Modes *modes, struct client *c, char *p);
|
||||||
struct aircraft *interactiveFindAircraft(uint32_t addr);
|
struct aircraft *interactiveFindAircraft(uint32_t addr);
|
||||||
struct stDF *interactiveFindDF (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
|
// Functions exported from net_io.c
|
||||||
//
|
//
|
||||||
void modesInitNet (void);
|
void modesInitNet (void);
|
||||||
void modesReadFromClients (void);
|
//void modesReadFromClients (void);
|
||||||
void modesSendAllClients (int service, void *msg, int len);
|
//void modesSendAllClients (int service, void *msg, int len);
|
||||||
void modesQueueOutput (struct modesMessage *mm);
|
//void modesQueueOutput (struct modesMessage *mm);
|
||||||
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
|
void modesReadFromClient (Modes *modes, struct client *c, char *sep, int(*handler)(Modes *modes, struct client *, char *));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
1
init.c
1
init.c
|
@ -48,7 +48,6 @@ void init(char *title) {
|
||||||
appData.mapTargetLat = 0;
|
appData.mapTargetLat = 0;
|
||||||
appData.mapTargetMaxDist = 0;
|
appData.mapTargetMaxDist = 0;
|
||||||
appData.isDragging = 0;
|
appData.isDragging = 0;
|
||||||
appData.selectedPlane = NULL;
|
|
||||||
|
|
||||||
if(appData.fullscreen) {
|
if(appData.fullscreen) {
|
||||||
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.
|
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.
|
||||||
|
|
202
interactive.c
202
interactive.c
|
@ -46,7 +46,7 @@ static uint64_t mstime(void) {
|
||||||
//
|
//
|
||||||
// Add a new DF structure to the interactive mode linked list
|
// 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));
|
struct stDF *pDF = (struct stDF *) malloc(sizeof(*pDF));
|
||||||
|
|
||||||
if (pDF) {
|
if (pDF) {
|
||||||
|
@ -60,60 +60,34 @@ void interactiveCreateDF(struct aircraft *a, struct modesMessage *mm) {
|
||||||
pDF->pAircraft = a;
|
pDF->pAircraft = a;
|
||||||
memcpy(pDF->msg, mm->msg, MODES_LONG_MSG_BYTES);
|
memcpy(pDF->msg, mm->msg, MODES_LONG_MSG_BYTES);
|
||||||
|
|
||||||
// if (!pthread_mutex_lock(&modes.pDF_mutex)) {
|
// if (!pthread_mutex_lock(&modes->pDF_mutex)) {
|
||||||
// if ((pDF->pNext = modes.pDF)) {
|
// if ((pDF->pNext = modes->pDF)) {
|
||||||
// modes.pDF->pPrev = pDF;
|
// modes->pDF->pPrev = pDF;
|
||||||
// }
|
// }
|
||||||
// modes.pDF = pDF;
|
// modes->pDF = pDF;
|
||||||
// pthread_mutex_unlock(&modes.pDF_mutex);
|
// pthread_mutex_unlock(&modes->pDF_mutex);
|
||||||
// } else {
|
// } else {
|
||||||
// free(pDF);
|
// free(pDF);
|
||||||
// }
|
// }
|
||||||
if ((pDF->pNext = modes.pDF)) {
|
if ((pDF->pNext = modes->pDF)) {
|
||||||
modes.pDF->pPrev = pDF;
|
modes->pDF->pPrev = pDF;
|
||||||
}
|
}
|
||||||
modes.pDF = pDF;
|
modes->pDF = pDF;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Remove stale DF's from the interactive mode linked list
|
// 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 *pDF = NULL;
|
||||||
struct stDF *prev = NULL;
|
struct stDF *prev = NULL;
|
||||||
|
|
||||||
// Only fiddle with the DF list if we gain possession of the mutex
|
pDF = modes->pDF;
|
||||||
// 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;
|
|
||||||
while(pDF) {
|
while(pDF) {
|
||||||
if ((now - pDF->seen) > modes.interactive_delete_ttl) {
|
if ((now - pDF->seen) > modes->interactive_delete_ttl) {
|
||||||
if (modes.pDF == pDF) {
|
if (modes->pDF == pDF) {
|
||||||
modes.pDF = NULL;
|
modes->pDF = NULL;
|
||||||
} else {
|
} else {
|
||||||
prev->pNext = NULL;
|
prev->pNext = NULL;
|
||||||
}
|
}
|
||||||
|
@ -131,32 +105,20 @@ void interactiveRemoveStaleDF(time_t now) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stDF *interactiveFindDF(uint32_t addr) {
|
// struct stDF *interactiveFindDF(Modes *modes, uint32_t addr) {
|
||||||
struct stDF *pDF = NULL;
|
// struct stDF *pDF = NULL;
|
||||||
|
|
||||||
// if (!pthread_mutex_lock(&modes.pDF_mutex)) {
|
// pDF = modes->pDF;
|
||||||
// pDF = modes.pDF;
|
|
||||||
// while(pDF) {
|
// while(pDF) {
|
||||||
// if (pDF->addr == addr) {
|
// if (pDF->addr == addr) {
|
||||||
// pthread_mutex_unlock (&modes.pDF_mutex);
|
|
||||||
// return (pDF);
|
// return (pDF);
|
||||||
// }
|
// }
|
||||||
// pDF = pDF->pNext;
|
// 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 ===============================
|
//========================= Interactive mode ===============================
|
||||||
//
|
//
|
||||||
|
@ -196,8 +158,8 @@ struct aircraft *interactiveCreateAircraft(struct modesMessage *mm) {
|
||||||
// Return the aircraft with the specified address, or NULL if no aircraft
|
// Return the aircraft with the specified address, or NULL if no aircraft
|
||||||
// exists with this address.
|
// exists with this address.
|
||||||
//
|
//
|
||||||
struct aircraft *interactiveFindAircraft(uint32_t addr) {
|
struct aircraft *interactiveFindAircraft(Modes *modes, uint32_t addr) {
|
||||||
struct aircraft *a = modes.aircrafts;
|
struct aircraft *a = modes->aircrafts;
|
||||||
|
|
||||||
while(a) {
|
while(a) {
|
||||||
if (a->addr == addr) return (a);
|
if (a->addr == addr) return (a);
|
||||||
|
@ -205,105 +167,25 @@ struct aircraft *interactiveFindAircraft(uint32_t addr) {
|
||||||
}
|
}
|
||||||
return (NULL);
|
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
|
// 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;
|
struct aircraft *a, *aux;
|
||||||
|
|
||||||
// Return if (checking crc) AND (not crcok) AND (not fixed)
|
// 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;
|
return NULL;
|
||||||
|
|
||||||
// Lookup our aircraft or create a new one
|
// 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....
|
if (!a) { // If it's a currently unknown aircraft....
|
||||||
a = interactiveCreateAircraft(mm); // ., create a new record for it,
|
a = interactiveCreateAircraft(mm); // ., create a new record for it,
|
||||||
a->next = modes.aircrafts; // .. and put it at the head of the list
|
a->next = modes->aircrafts; // .. and put it at the head of the list
|
||||||
modes.aircrafts = a;
|
modes->aircrafts = a;
|
||||||
} else {
|
} else {
|
||||||
/* If it is an already known aircraft, move it on head
|
/* If it is an already known aircraft, move it on head
|
||||||
* so we keep aircrafts ordered by received message time.
|
* 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,
|
* since the aircraft that is currently on head sent a message,
|
||||||
* othewise with multiple aircrafts at the same time we have an
|
* othewise with multiple aircrafts at the same time we have an
|
||||||
* useless shuffle of positions on the screen. */
|
* useless shuffle of positions on the screen. */
|
||||||
if (0 && modes.aircrafts != a && (time(NULL) - a->seen) >= 1) {
|
if (0 && modes->aircrafts != a && (time(NULL) - a->seen) >= 1) {
|
||||||
aux = modes.aircrafts;
|
aux = modes->aircrafts;
|
||||||
while(aux->next != a) aux = aux->next;
|
while(aux->next != a) aux = aux->next;
|
||||||
/* Now we are a node before the aircraft to remove. */
|
/* Now we are a node before the aircraft to remove. */
|
||||||
aux->next = aux->next->next; /* removed. */
|
aux->next = aux->next->next; /* removed. */
|
||||||
/* Add on head */
|
/* Add on head */
|
||||||
a->next = modes.aircrafts;
|
a->next = modes->aircrafts;
|
||||||
modes.aircrafts = a;
|
modes->aircrafts = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,13 +274,13 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
||||||
|
|
||||||
// If we have enough recent data, try global CPR
|
// 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 (((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;
|
location_ok = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise try relative CPR.
|
// 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;
|
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 we are Logging DF's, and it's not a Mode A/C
|
||||||
if ((modes.bEnableDFLogging) && (mm->msgtype < 32)) {
|
if ((modes->bEnableDFLogging) && (mm->msgtype < 32)) {
|
||||||
interactiveCreateDF(a,mm);
|
interactiveCreateDF(modes,a,mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (a);
|
return (a);
|
||||||
|
@ -445,23 +327,23 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
|
||||||
// When in interactive mode If we don't receive new nessages within
|
// When in interactive mode If we don't receive new nessages within
|
||||||
// MODES_INTERACTIVE_DELETE_TTL seconds we remove the aircraft from the list.
|
// MODES_INTERACTIVE_DELETE_TTL seconds we remove the aircraft from the list.
|
||||||
//
|
//
|
||||||
void interactiveRemoveStaleAircrafts(void) {
|
void interactiveRemoveStaleAircrafts(Modes *modes) {
|
||||||
struct aircraft *a = modes.aircrafts;
|
struct aircraft *a = modes->aircrafts;
|
||||||
struct aircraft *prev = NULL;
|
struct aircraft *prev = NULL;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
||||||
// Only do cleanup once per second
|
// Only do cleanup once per second
|
||||||
if (modes.last_cleanup_time != now) {
|
if (modes->last_cleanup_time != now) {
|
||||||
modes.last_cleanup_time = now;
|
modes->last_cleanup_time = now;
|
||||||
|
|
||||||
interactiveRemoveStaleDF(now);
|
interactiveRemoveStaleDF(modes,now);
|
||||||
|
|
||||||
while(a) {
|
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
|
// Remove the element from the linked list, with care
|
||||||
// if we are removing the first element
|
// if we are removing the first element
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
modes.aircrafts = a->next; free(a); a = modes.aircrafts;
|
modes->aircrafts = a->next; free(a); a = modes->aircrafts;
|
||||||
} else {
|
} else {
|
||||||
prev->next = a->next; free(a); a = prev->next;
|
prev->next = a->next; free(a); a = prev->next;
|
||||||
}
|
}
|
||||||
|
|
152
map1090.cpp
Normal file
152
map1090.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//=========================================================================
|
||||||
|
//
|
|
@ -1 +0,0 @@
|
||||||
aaf101fcf91be4f20921260cd579f3fa5dda321e
|
|
250
net_io.c
250
net_io.c
|
@ -55,102 +55,18 @@ struct service {
|
||||||
|
|
||||||
struct service services[MODES_NET_SERVICES_NUM];
|
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.
|
// 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
|
// Unhook this client from the linked list of clients
|
||||||
struct client *p = modes.clients;
|
struct client *p = modes->clients;
|
||||||
if (p) {
|
if (p) {
|
||||||
if (p == c) {
|
if (p == c) {
|
||||||
modes.clients = c->next;
|
modes->clients = c->next;
|
||||||
} else {
|
} else {
|
||||||
while ((p) && (p->next != c)) {
|
while ((p) && (p->next != c)) {
|
||||||
p = p->next;
|
p = p->next;
|
||||||
|
@ -168,17 +84,17 @@ void modesFreeClient(struct client *c) {
|
||||||
//
|
//
|
||||||
// Close the client connection and mark it as closed
|
// Close the client connection and mark it as closed
|
||||||
//
|
//
|
||||||
void modesCloseClient(struct client *c) {
|
void modesCloseClient(Modes *modes, struct client *c) {
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
if (c->service == modes.sbsos) {
|
if (c->service == modes->sbsos) {
|
||||||
if (modes.stat_sbs_connections) modes.stat_sbs_connections--;
|
if (modes->stat_sbs_connections) modes->stat_sbs_connections--;
|
||||||
} else if (c->service == modes.ros) {
|
} else if (c->service == modes->ros) {
|
||||||
if (modes.stat_raw_connections) modes.stat_raw_connections--;
|
if (modes->stat_raw_connections) modes->stat_raw_connections--;
|
||||||
} else if (c->service == modes.bos) {
|
} else if (c->service == modes->bos) {
|
||||||
if (modes.stat_beast_connections) modes.stat_beast_connections--;
|
if (modes->stat_beast_connections) modes->stat_beast_connections--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modes.debug & MODES_DEBUG_NET)
|
if (modes->debug & MODES_DEBUG_NET)
|
||||||
printf("Closing client %d\n", c->fd);
|
printf("Closing client %d\n", c->fd);
|
||||||
|
|
||||||
c->fd = -1;
|
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
|
// 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.
|
// 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 msgLen = 0;
|
||||||
int j;
|
int j;
|
||||||
char ch;
|
char ch;
|
||||||
|
@ -209,7 +125,7 @@ int decodeBinMessage(struct client *c, char *p) {
|
||||||
ch = *p++; /// Get the message type
|
ch = *p++; /// Get the message type
|
||||||
if (0x1A == ch) {p++;}
|
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;
|
msgLen = MODEAC_MSG_BYTES;
|
||||||
} else if (ch == '2') {
|
} else if (ch == '2') {
|
||||||
msgLen = MODES_SHORT_MSG_BYTES;
|
msgLen = MODES_SHORT_MSG_BYTES;
|
||||||
|
@ -236,13 +152,13 @@ int decodeBinMessage(struct client *c, char *p) {
|
||||||
if (0x1A == ch) {p++;}
|
if (0x1A == ch) {p++;}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
|
// if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC
|
||||||
decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
|
// decodeModeAMessage(modes, &mm, ((msg[0] << 8) | msg[1]));
|
||||||
} else {
|
// } else {
|
||||||
decodeModesMessage(&mm, msg);
|
decodeModesMessage(modes, &mm, msg);
|
||||||
}
|
//}
|
||||||
|
|
||||||
useModesMessage(&mm);
|
useModesMessage(modes, &mm);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -259,91 +175,6 @@ int hexDigitVal(int c) {
|
||||||
else return -1;
|
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
|
// 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.
|
// close the connection with the client in case of non-recoverable errors.
|
||||||
//
|
//
|
||||||
void modesReadFromClient(struct client *c, char *sep,
|
void modesReadFromClient(Modes *modes, struct client *c, char *sep,
|
||||||
int(*handler)(struct client *, char *)) {
|
int(*handler)(Modes *modes, struct client *, char *)) {
|
||||||
int left;
|
int left;
|
||||||
int nread;
|
int nread;
|
||||||
int fullmsg;
|
int fullmsg;
|
||||||
|
@ -384,7 +215,7 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
if (nread < 0) {errno = WSAGetLastError();}
|
if (nread < 0) {errno = WSAGetLastError();}
|
||||||
#endif
|
#endif
|
||||||
if (nread == 0) {
|
if (nread == 0) {
|
||||||
modesCloseClient(c);
|
modesCloseClient(modes, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +228,7 @@ void modesReadFromClient(struct client *c, char *sep,
|
||||||
#else
|
#else
|
||||||
if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file
|
if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file
|
||||||
#endif
|
#endif
|
||||||
modesCloseClient(c);
|
modesCloseClient(modes, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nread <= 0) {
|
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.
|
// This is the Beast Binary scanning case.
|
||||||
// If there is a complete message still in the buffer, there must be the separator 'sep'
|
// 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.
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
// Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
|
// Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler.
|
||||||
if (handler(c, s)) {
|
if (handler(modes, c, s)) {
|
||||||
modesCloseClient(c);
|
modesCloseClient(modes, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fullmsg = 1;
|
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
|
while ((e = strstr(s, sep)) != NULL) { // end of first message if found
|
||||||
*e = '\0'; // The handler expects null terminated strings
|
*e = '\0'; // The handler expects null terminated strings
|
||||||
if (handler(c, s)) { // Pass message to handler.
|
if (handler(modes, c, s)) { // Pass message to handler.
|
||||||
modesCloseClient(c); // Handler returns 1 on error to signal we .
|
modesCloseClient(modes, c); // Handler returns 1 on error to signal we .
|
||||||
return; // should close the client connection
|
return; // should close the client connection
|
||||||
}
|
}
|
||||||
s = e + strlen(sep); // Move to start of next message
|
s = e + strlen(sep); // Move to start of next message
|
||||||
|
@ -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 ===========================
|
|
||||||
//
|
|
||||||
|
|
66
status.c
66
status.c
|
@ -13,66 +13,26 @@ void updateStatus() {
|
||||||
double sigAccumulate = 0.0;
|
double sigAccumulate = 0.0;
|
||||||
double msgRateAccumulate = 0.0;
|
double msgRateAccumulate = 0.0;
|
||||||
|
|
||||||
/*
|
|
||||||
while(a) {
|
|
||||||
int flags = a->modeACflags;
|
|
||||||
int msgs = a->messages;
|
|
||||||
|
|
||||||
if ( (((flags & (MODEAC_MSG_FLAG )) == 0 ) )
|
// PlaneObj *p = appData.planes;
|
||||||
|| (((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) )
|
|
||||||
) {
|
|
||||||
|
|
||||||
unsigned char * pSig = a->signalLevel;
|
// while(p) {
|
||||||
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
// unsigned char * pSig = p->signalLevel;
|
||||||
pSig[4] + pSig[5] + pSig[6] + pSig[7]);
|
// 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) {
|
// if (p->lon && p->lat) {
|
||||||
double d = sqrt(a->dx * a->dx + a->dy * a->dy);
|
// numVisiblePlanes++;
|
||||||
|
// }
|
||||||
|
|
||||||
if(d < appData.maxDist) {
|
// totalCount++;
|
||||||
if(d > maxDist) {
|
|
||||||
maxDist = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d < 4.0) {
|
// msgRateAccumulate += p->messageRate;
|
||||||
Status.closeCall = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
numVisiblePlanes++;
|
// p = p->next;
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status.msgRate = msgRateAccumulate;
|
Status.msgRate = msgRateAccumulate;
|
||||||
Status.avgSig = sigAccumulate / (double) totalCount;
|
Status.avgSig = sigAccumulate / (double) totalCount;
|
||||||
|
|
52
structs.h
52
structs.h
|
@ -3,42 +3,7 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
#include "AircraftData.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;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct AppData
|
typedef struct AppData
|
||||||
|
@ -93,8 +58,8 @@ typedef struct AppData
|
||||||
|
|
||||||
QuadTree root;
|
QuadTree root;
|
||||||
|
|
||||||
PlaneObj *planes;
|
//PlaneObj *planes;
|
||||||
PlaneObj *selectedPlane;
|
//PlaneObj *selectedPlane;
|
||||||
|
|
||||||
uint64_t lastFrameTime;
|
uint64_t lastFrameTime;
|
||||||
} AppData;
|
} AppData;
|
||||||
|
@ -142,28 +107,17 @@ void drawStringBG(char *, int, int, TTF_Font *, SDL_Color, SDL_Color);
|
||||||
void init(char *);
|
void init(char *);
|
||||||
void cleanup(void);
|
void cleanup(void);
|
||||||
|
|
||||||
//input.c
|
|
||||||
void getInput(void);
|
|
||||||
|
|
||||||
//mapdata.c
|
//mapdata.c
|
||||||
void initMaps();
|
void initMaps();
|
||||||
|
|
||||||
//list.c
|
//list.c
|
||||||
void drawList(int top);
|
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
|
//status.c
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
void drawStatus();
|
void drawStatus();
|
||||||
|
|
||||||
//planeObj.c
|
|
||||||
void updatePlanes();
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "view1090.h"
|
#include "view1090.h"
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
#include "AircraftData.h"
|
||||||
|
|
||||||
int go = 1;
|
int go = 1;
|
||||||
|
|
||||||
|
@ -37,117 +38,26 @@ int go = 1;
|
||||||
AppData appData;
|
AppData appData;
|
||||||
Style style;
|
Style style;
|
||||||
|
|
||||||
Modes modes;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// ============================= Utility functions ==========================
|
// ============================= Utility functions ==========================
|
||||||
//
|
//
|
||||||
void sigintHandler(int dummy) {
|
void sigintHandler(int dummy) {
|
||||||
NOTUSED(dummy);
|
NOTUSED(dummy);
|
||||||
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
|
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
|
// Set up data connection
|
||||||
int setupConnection(struct client *c) {
|
int setupConnection(struct client *c) {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
// Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here.
|
// 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) {
|
if ((fd = anetTcpConnect(AircraftData.modes.aneterr, View1090.net_input_beast_ipaddr, AircraftData.modes.net_input_beast_port)) != ANET_ERR) {
|
||||||
anetNonBlock(modes.aneterr, fd);
|
anetNonBlock(AircraftData.modes.aneterr, fd);
|
||||||
//
|
//
|
||||||
// Setup a service callback client structure for a beast binary input (from dump1090)
|
// 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
|
// 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->buflen = 0;
|
||||||
c->fd =
|
c->fd =
|
||||||
c->service =
|
c->service =
|
||||||
modes.bis = fd;
|
AircraftData.modes.bis = fd;
|
||||||
modes.clients = c;
|
AircraftData.modes.clients = c;
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -232,31 +142,33 @@ int main(int argc, char **argv) {
|
||||||
struct client *c;
|
struct client *c;
|
||||||
char pk_buf[8];
|
char pk_buf[8];
|
||||||
|
|
||||||
// Set sane defaults
|
AircraftData aircraftData;
|
||||||
|
|
||||||
view1090InitConfig();
|
|
||||||
signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)
|
signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)
|
||||||
|
|
||||||
|
|
||||||
|
aircraftData.initialize();
|
||||||
|
|
||||||
// Parse the command line options
|
// Parse the command line options
|
||||||
for (j = 1; j < argc; j++) {
|
for (j = 1; j < argc; j++) {
|
||||||
int more = ((j + 1) < argc); // There are more arguments
|
int more = ((j + 1) < argc); // There are more arguments
|
||||||
|
|
||||||
if (!strcmp(argv[j],"--net-bo-port") && more) {
|
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) {
|
} 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) {
|
} else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) {
|
||||||
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
|
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--server") && more) {
|
} else if (!strcmp(argv[j],"--server") && more) {
|
||||||
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
|
strcpy(View1090.net_input_beast_ipaddr, argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--lat") && more) {
|
} else if (!strcmp(argv[j],"--lat") && more) {
|
||||||
modes.fUserLat = atof(argv[++j]);
|
AircraftData.modes.fUserLat = atof(argv[++j]);
|
||||||
appData.centerLat = modes.fUserLat;
|
appData.centerLat = AircraftData.modes.fUserLat;
|
||||||
} else if (!strcmp(argv[j],"--lon") && more) {
|
} else if (!strcmp(argv[j],"--lon") && more) {
|
||||||
modes.fUserLon = atof(argv[++j]);
|
AircraftData.modes.fUserLon = atof(argv[++j]);
|
||||||
appData.centerLon = modes.fUserLon;
|
appData.centerLon = AircraftData.modes.fUserLon;
|
||||||
} else if (!strcmp(argv[j],"--metric")) {
|
} else if (!strcmp(argv[j],"--metric")) {
|
||||||
modes.metric = 1;
|
AircraftData.modes.metric = 1;
|
||||||
} else if (!strcmp(argv[j],"--fullscreen")) {
|
} else if (!strcmp(argv[j],"--fullscreen")) {
|
||||||
appData.fullscreen = 1;
|
appData.fullscreen = 1;
|
||||||
} else if (!strcmp(argv[j],"--uiscale") && more) {
|
} 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.
|
// 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));
|
c = (struct client *) malloc(sizeof(*c));
|
||||||
while(1) {
|
while(1) {
|
||||||
if ((fd = setupConnection(c)) == ANET_ERR) {
|
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);
|
sleep(1);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
Loading…
Reference in a new issue