clean up
This commit is contained in:
parent
52338202d1
commit
2f9c3fe0e1
283
net_io.c
283
net_io.c
|
|
@ -780,16 +780,10 @@ static void send_sbs_heartbeat(struct net_service *service)
|
||||||
completeWrite(service->writer, data + len);
|
completeWrite(service->writer, data + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////// Start Stratux block
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
// Write Stratux output to TCP clients
|
// Write Stratux output to TCP clients
|
||||||
// The message structure mm->bFlags tells us what has been updated by this message
|
|
||||||
//
|
|
||||||
// Output format is a JSON representation of a subset of the fields used in the
|
|
||||||
// Stratux traffic structure.
|
|
||||||
//
|
//
|
||||||
static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a) {
|
static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
@ -813,11 +807,17 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
|
||||||
if (!mm->reliable && !a->reliable)
|
if (!mm->reliable && !a->reliable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//// For now, suppress non-ICAO addresses
|
||||||
|
//if (mm->addr & MODES_NON_ICAO_ADDRESS)
|
||||||
|
// return;
|
||||||
|
|
||||||
p = prepareWrite(&Modes.stratux_out, 1000); // larger buffer size needed vs SBS
|
p = prepareWrite(&Modes.stratux_out, 1000); // larger buffer size needed vs SBS
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// NOTE: not sure about message types, so keep the original code from
|
||||||
|
// stratux/dump1090 as-is.
|
||||||
|
//
|
||||||
// Decide on the basic SBS Message Type
|
// Decide on the basic SBS Message Type
|
||||||
if ((mm->msgtype == 4) || (mm->msgtype == 20)) {
|
if ((mm->msgtype == 4) || (mm->msgtype == 20)) {
|
||||||
msgType = 5;
|
msgType = 5;
|
||||||
|
|
@ -842,7 +842,7 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
|
||||||
else
|
else
|
||||||
{msgType = 7;}
|
{msgType = 7;}
|
||||||
} else if ((mm->metype == 29) || (mm->metype == 31)) {
|
} else if ((mm->metype == 29) || (mm->metype == 31)) {
|
||||||
msgType = 9; // new message type for target state and operational status messages
|
msgType = 9; // new message type for target state and operational status messages
|
||||||
} else if (mm->metype != 19) {
|
} else if (mm->metype != 19) {
|
||||||
return;
|
return;
|
||||||
} else if ((mm->mesub == 1) || (mm->mesub == 2)) {
|
} else if ((mm->mesub == 1) || (mm->mesub == 2)) {
|
||||||
|
|
@ -852,146 +852,163 @@ static void modesSendStratuxOutput(struct modesMessage *mm, struct aircraft *a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin populating the traffic.go fields.
|
// Begin populating the traffic.go fields.
|
||||||
// ICAO address, Mode S message types, and signal level
|
// ICAO address, Mode S message types, and signal level
|
||||||
|
|
||||||
int cacf = 0; // overload the JSON "CA" field to report CA (DF11 or DF17), CF (DF18), or zero (all other DF types)
|
int cacf = 0; // overload the JSON "CA" field to report CA (DF11 or DF17), CF (DF18), or zero (all other DF types)
|
||||||
if ((mm->msgtype == 11) || (mm->msgtype == 17)) {
|
if ((mm->msgtype == 11) || (mm->msgtype == 17)) {
|
||||||
cacf = mm->CA;
|
cacf = mm->CA;
|
||||||
} else if (mm->msgtype == 18) {
|
} else if (mm->msgtype == 18) {
|
||||||
cacf = mm->CF;
|
cacf = mm->CF;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += sprintf(p, "{\"Icao_addr\":%d,\"DF\":%d,\"CA\":%d,\"TypeCode\":%d,\"SubtypeCode\":%d,\"SBS_MsgType\":%d,\"SignalLevel\":%f,",mm->addr, mm->msgtype, cacf, mm->metype, mm->mesub, msgType, mm->signalLevel); // what precision and range is needed for RSSI?
|
|
||||||
|
|
||||||
// Callsign
|
|
||||||
if (mm->callsign_valid) {
|
|
||||||
p += sprintf(p, "\"Tail\":\"%s\",", mm->callsign);
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"Tail\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Squawk
|
|
||||||
if (mm->squawk_valid) {
|
|
||||||
p += sprintf(p, "\"Squawk\":%x,", mm->squawk);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p += sprintf(p, "\"Squawk\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emitter type
|
|
||||||
int emitter = 0;
|
|
||||||
int setEmitter = 0;
|
|
||||||
if ((mm->msgtype == 17) || (mm->msgtype == 18)) {
|
|
||||||
switch (mm->metype) {
|
|
||||||
case 1:
|
|
||||||
emitter = ((mm->mesub) | 0x18);
|
|
||||||
setEmitter = 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
emitter = ((mm->mesub) | 0x10);
|
|
||||||
setEmitter = 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
emitter = ((mm->mesub) | 0x08);
|
|
||||||
setEmitter = 1;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
emitter = (mm->mesub);
|
|
||||||
setEmitter = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setEmitter) {
|
|
||||||
p += sprintf(p, "\"Emitter_category\":%d,", emitter);
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"Emitter_category\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnGround
|
|
||||||
if (mm->airground == AG_GROUND) {
|
|
||||||
p += sprintf(p, "\"OnGround\":true,");
|
|
||||||
} else if (mm->airground == AG_AIRBORNE) {
|
|
||||||
p += sprintf(p, "\"OnGround\":false,");
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"OnGround\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position and position valid flag
|
|
||||||
if (mm->cpr_decoded) {
|
|
||||||
p += sprintf(p, "\"Lat\":%.6f,\"Lng\":%.6f,\"Position_valid\":true,", mm->decoded_lat, mm->decoded_lon);
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"Lat\":null,\"Lng\":null,\"Position_valid\":false,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation Accuracy Category - Position
|
|
||||||
if (mm->accuracy.nac_p_valid) {
|
|
||||||
p += sprintf(p, "\"NACp\":%d,", mm->accuracy.nac_p);
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"NACp\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool alt_is_geom = false;
|
|
||||||
// Altitude
|
|
||||||
if (Modes.use_gnss && mm->altitude_geom_valid) {
|
|
||||||
p += sprintf(p, "\"Alt\":%d,",mm->altitude_geom);
|
|
||||||
alt_is_geom = true;
|
|
||||||
} else if (mm->altitude_baro_valid) {
|
|
||||||
p += sprintf(p, "\"Alt\":%d,",mm->altitude_baro);
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"Alt\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Altitude Source. True if altitude source is GNSS, false if pressure altitude.
|
|
||||||
if (alt_is_geom) {
|
|
||||||
p += sprintf(p, "\"AltIsGNSS\":true,");
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"AltIsGNSS\":false,");
|
|
||||||
}
|
|
||||||
// GNSS Alt Diff From Baro Alt
|
|
||||||
if (trackDataValid(&a->geom_delta_valid)) {
|
|
||||||
p += sprintf(p, "\"GnssDiffFromBaroAlt\":%d,",a->geom_delta); // Verify that this is part of a and not mm
|
|
||||||
} else {
|
|
||||||
p += sprintf(p, "\"GnssDiffFromBaroAlt\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Vertical velocity
|
|
||||||
if (alt_is_geom) {
|
|
||||||
if (mm->geom_rate_valid)
|
|
||||||
p += sprintf(p, "\"Vvel\":%d,", mm->geom_rate);
|
|
||||||
else
|
|
||||||
p += sprintf(p, "\"Vvel\":null,");
|
|
||||||
} else {
|
|
||||||
if (mm->baro_rate_valid)
|
|
||||||
p += sprintf(p, "\"Vvel\":%d,", mm->baro_rate);
|
|
||||||
else
|
|
||||||
p += sprintf(p, "\"Vvel\":null,");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ground speed and track
|
p += sprintf(p,
|
||||||
if (mm->gs_valid) {
|
"{\"Icao_addr\":%d,"
|
||||||
p += sprintf(p, "\"Speed_valid\":true,\"Speed\":%.0f,", mm->gs.selected);
|
"\"DF\":%d,\"CA\":%d,"
|
||||||
} else {
|
"\"TypeCode\":%d,"
|
||||||
p += sprintf(p, "\"Speed_valid\":false,\"Speed\":null,");
|
"\"SubtypeCode\":%d,"
|
||||||
}
|
"\"SBS_MsgType\":%d,"
|
||||||
|
"\"SignalLevel\":%f,",
|
||||||
if (mm->heading_valid && mm->heading_type == HEADING_GROUND_TRACK) {
|
mm->addr,
|
||||||
p += sprintf(p, "\"Track\":%.0f,", mm->heading);
|
mm->msgtype, cacf,
|
||||||
} else {
|
mm->metype,
|
||||||
p += sprintf(p, "\"Track\":null,");
|
mm->mesub,
|
||||||
}
|
msgType,
|
||||||
|
mm->signalLevel); // what precision and range is needed for RSSI?
|
||||||
|
|
||||||
// Find current system time
|
// Find current system time
|
||||||
clock_gettime(CLOCK_REALTIME, &now);
|
clock_gettime(CLOCK_REALTIME, &now);
|
||||||
gmtime_r(&now.tv_sec, &stTime_now); // we expect UTC
|
gmtime_r(&now.tv_sec, &stTime_now); // we expect UTC
|
||||||
|
|
||||||
// Find message reception time
|
// Find message reception time
|
||||||
time_t received = (time_t) (mm->sysTimestampMsg / 1000);
|
time_t received = (time_t) (mm->sysTimestampMsg / 1000);
|
||||||
localtime_r(&received, &stTime_receive);
|
localtime_r(&received, &stTime_receive);
|
||||||
|
|
||||||
//Time message received (based on system clock). Format is 2016-02-20T06:35:43.155Z
|
// Time message received (based on system clock). Format is 2016-02-20T06:35:43.155Z
|
||||||
p += sprintf(p, "\"Timestamp\":\"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ\"", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday, stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, (unsigned) (mm->sysTimestampMsg % 1000));
|
p += sprintf(p, "\"Timestamp\":\"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ\"", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday, stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, (unsigned) (mm->sysTimestampMsg % 1000));
|
||||||
|
|
||||||
|
//// callsign
|
||||||
|
if (mm->callsign_valid)
|
||||||
|
p += sprintf(p, "\"Tail\":\"%s\",", mm->callsign);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Tail\":null,");
|
||||||
|
|
||||||
|
//// altitude & gnss
|
||||||
|
bool alt_is_geom = false;
|
||||||
|
if (Modes.use_gnss && mm->altitude_geom_valid) {
|
||||||
|
p += sprintf(p, "\"Alt\":%d,",mm->altitude_geom);
|
||||||
|
alt_is_geom = true;
|
||||||
|
} else if (mm->altitude_baro_valid)
|
||||||
|
p += sprintf(p, "\"Alt\":%d,",mm->altitude_baro);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Alt\":null,");
|
||||||
|
|
||||||
|
// altitude source
|
||||||
|
if (alt_is_geom)
|
||||||
|
p += sprintf(p, "\"AltIsGNSS\":true,");
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"AltIsGNSS\":false,");
|
||||||
|
|
||||||
|
// GNSS alt. delta From baro alt.
|
||||||
|
if (trackDataValid(&a->geom_delta_valid))
|
||||||
|
p += sprintf(p, "\"GnssDiffFromBaroAlt\":%d,",a->geom_delta);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"GnssDiffFromBaroAlt\":null,");
|
||||||
|
////
|
||||||
|
|
||||||
|
//// ground speed and track
|
||||||
|
if (mm->gs_valid)
|
||||||
|
p += sprintf(p, "\"Speed_valid\":true,\"Speed\":%.0f,", mm->gs.selected);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Speed_valid\":false,\"Speed\":null,");
|
||||||
|
|
||||||
|
//// ground heading
|
||||||
|
if (mm->heading_valid && mm->heading_type == HEADING_GROUND_TRACK)
|
||||||
|
p += sprintf(p, "\"Track\":%.0f,", mm->heading);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Track\":null,");
|
||||||
|
|
||||||
|
//// position
|
||||||
|
if (mm->cpr_decoded)
|
||||||
|
p += sprintf(p, "\"Lat\":%.6f,\"Lng\":%.6f,\"Position_valid\":true,",
|
||||||
|
mm->decoded_lat, mm->decoded_lon);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Lat\":null,\"Lng\":null,\"Position_valid\":false,");
|
||||||
|
|
||||||
|
//// vrate
|
||||||
|
if (Modes.use_gnss) {
|
||||||
|
if (mm->geom_rate_valid)
|
||||||
|
p += sprintf(p, "\"Vvel\":%d,", mm->geom_rate);
|
||||||
|
else if (mm->baro_rate_valid)
|
||||||
|
p += sprintf(p, "\"Vvel\":%d,", mm->baro_rate);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Vvel\":null,");
|
||||||
|
} else {
|
||||||
|
if (mm->baro_rate_valid)
|
||||||
|
p += sprintf(p, "\"Vvel\":%d,", mm->baro_rate);
|
||||||
|
else if (mm->geom_rate_valid)
|
||||||
|
p += sprintf(p, "\"Vvel\":%d,", mm->geom_rate);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Vvel\":null,");
|
||||||
|
}
|
||||||
|
|
||||||
|
//// squawk
|
||||||
|
if (mm->squawk_valid)
|
||||||
|
p += sprintf(p, "\"Squawk\":%x,", mm->squawk);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Squawk\":null,");
|
||||||
|
|
||||||
|
// TODO: squawk changing alert support in stratux?
|
||||||
|
// TODO: squawk emergency flag?
|
||||||
|
// TODO: squawk ident flag?
|
||||||
|
|
||||||
|
// airground
|
||||||
|
switch (mm->airground) {
|
||||||
|
case AG_GROUND:
|
||||||
|
p += sprintf(p, "\"OnGround\":true,");
|
||||||
|
break;
|
||||||
|
case AG_AIRBORNE:
|
||||||
|
p += sprintf(p, "\"OnGround\":false,");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
p += sprintf(p, "\"OnGround\":null,");
|
||||||
|
}
|
||||||
|
|
||||||
|
// navigation accuracy category - position
|
||||||
|
if (mm->accuracy.nac_p_valid) {
|
||||||
|
p += sprintf(p, "\"NACp\":%d,", mm->accuracy.nac_p);
|
||||||
|
} else {
|
||||||
|
p += sprintf(p, "\"NACp\":null,");
|
||||||
|
}
|
||||||
|
|
||||||
|
// emitter type
|
||||||
|
int emitter = 0;
|
||||||
|
int setEmitter = 0;
|
||||||
|
if ((mm->msgtype == 17) || (mm->msgtype == 18)) {
|
||||||
|
switch (mm->metype) {
|
||||||
|
case 1:
|
||||||
|
emitter = ((mm->mesub) | 0x18);
|
||||||
|
setEmitter = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
emitter = ((mm->mesub) | 0x10);
|
||||||
|
setEmitter = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
emitter = ((mm->mesub) | 0x08);
|
||||||
|
setEmitter = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
emitter = (mm->mesub);
|
||||||
|
setEmitter = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setEmitter)
|
||||||
|
p += sprintf(p, "\"Emitter_category\":%d,", emitter);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "\"Emitter_category\":null,");
|
||||||
|
|
||||||
p += sprintf(p, "}\r\n");
|
p += sprintf(p, "}\r\n");
|
||||||
|
|
||||||
completeWrite(&Modes.stratux_out, p);
|
completeWrite(&Modes.stratux_out, p);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue