From 564f0330873fcbd04bfce1c16c6dfdc992fe52ee Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Thu, 2 May 2019 17:29:46 +0800 Subject: [PATCH] Add some oneoff tools for comm-b decoding testing --- Makefile | 3 + oneoff/decode_comm_b.c | 172 +++++++++++++++++++++++++++++++++++++++ oneoff/extract-comm-b.py | 17 ++++ 3 files changed, 192 insertions(+) create mode 100644 oneoff/decode_comm_b.c create mode 100755 oneoff/extract-comm-b.py diff --git a/Makefile b/Makefile index 6cc6f97..6343ffb 100644 --- a/Makefile +++ b/Makefile @@ -70,3 +70,6 @@ benchmarks: convert_benchmark oneoff/convert_benchmark: oneoff/convert_benchmark.o convert.o util.o $(CC) $(CPPFLAGS) $(CFLAGS) -g -o $@ $^ -lm + +oneoff/decode_comm_b: oneoff/decode_comm_b.o comm_b.o ais_charset.o + $(CC) $(CPPFLAGS) $(CFLAGS) -g -o $@ $^ -lm diff --git a/oneoff/decode_comm_b.c b/oneoff/decode_comm_b.c new file mode 100644 index 0000000..50f64a6 --- /dev/null +++ b/oneoff/decode_comm_b.c @@ -0,0 +1,172 @@ +#include + +#include "../dump1090.h" +#include "../comm_b.h" + +char last_callsign[8]; +double last_callsign_ts = 0; +double last_track = -1; +double last_track_ts = 0; +double last_magnetic = -1; +double last_magnetic_ts = 0; +double last_gs = -1; +double last_gs_ts = 0; +double last_ias = -1; +double last_ias_ts = 0; +double last_tas = -1; +double last_tas_ts = 0; +double last_mach = -1; +double last_mach_ts = 0; + +double angle_difference(double h1, double h2) +{ + float delta = fabs(h1 - h2); + if (delta > 180.0) + delta = 360.0 - delta; + return delta; +} + +void process(double timestamp, const char *line, struct modesMessage *mm) +{ + decodeCommB(mm); + + printf("line\t%s\tformat\t", line); + + switch (mm->commb_format) { +#define EMIT(x) case COMMB_ ## x: printf("%s", #x); break + EMIT(UNKNOWN); + EMIT(AMBIGUOUS); + EMIT(EMPTY_RESPONSE); + EMIT(DATALINK_CAPS); + EMIT(GICB_CAPS); + EMIT(AIRCRAFT_IDENT); + EMIT(ACAS_RA); + EMIT(VERTICAL_INTENT); + EMIT(TRACK_TURN); + EMIT(HEADING_SPEED); +#undef EMIT + default: + printf("%s", "UNHANDLED"); break; + } + + int suspicious = 0; + + if (mm->callsign_valid) { + printf("\tcallsign\t%s", mm->callsign); + if ((timestamp - last_callsign_ts) < 30.0 && strcmp(last_callsign, mm->callsign)) { + suspicious = 1; + } + memcpy(last_callsign, mm->callsign, sizeof(last_callsign)); + last_callsign_ts = timestamp; + } + if (mm->heading_valid && mm->heading_type == HEADING_GROUND_TRACK) { + printf("\ttrack\t%.1f", mm->heading); + if ((timestamp - last_track_ts) < 10.0 && angle_difference(last_track, mm->heading) > 45) { + suspicious = 1; + } + if ((timestamp - last_magnetic_ts) < 10.0 && angle_difference(last_magnetic, mm->heading) > 45) { + suspicious = 1; + } + last_track = mm->heading; + last_track_ts = timestamp; + } + if (mm->heading_valid && mm->heading_type == HEADING_MAGNETIC) { + printf("\tmagnetic\t%.1f", mm->heading); + if ((timestamp - last_magnetic_ts) < 10.0 && angle_difference(last_magnetic, mm->heading) > 45) { + suspicious = 1; + } + if ((timestamp - last_track_ts) < 10.0 && angle_difference(last_track, mm->heading) > 45) { + suspicious = 1; + } + last_magnetic = mm->heading; + last_magnetic_ts = timestamp; + } + if (mm->track_rate_valid) { + printf("\ttrack_rate\t%.2f", mm->track_rate); + } + if (mm->roll_valid) { + printf("\troll\t%.1f", mm->roll); + } + if (mm->gs_valid) { + printf("\tgs\t%.1f", mm->gs.selected); + if ((timestamp - last_gs_ts) < 10.0 && fabs(last_gs - mm->gs.selected) > 50) { + suspicious = 1; + } + last_gs = mm->gs.selected; + last_gs_ts = timestamp; + } + if (mm->ias_valid) { + printf("\tias\t%d", mm->ias); + if ((timestamp - last_ias_ts) < 10.0 && abs(last_ias - mm->ias) > 50) { + suspicious = 1; + } + last_ias = mm->ias; + last_ias_ts = timestamp; + } + if (mm->tas_valid) { + printf("\ttas\t%d", mm->tas); + if ((timestamp - last_tas_ts) < 10.0 && abs(last_tas - mm->tas) > 50) { + suspicious = 1; + } + last_tas = mm->tas; + last_tas_ts = timestamp; + } + if (mm->mach_valid) { + printf("\tmach\t%.3f", mm->mach); + if ((timestamp - last_mach_ts) < 10.0 && abs(last_mach - mm->mach) > 0.1) { + suspicious = 1; + } + last_mach = mm->mach; + last_mach_ts = timestamp; + } + + if (suspicious) { + printf("\tsuspicious\tyes!"); + } + + printf("\n"); +} + +int main(int argc, char **argv) +{ + /* unused */ (void)argc; + /* unused */ (void)argv; + + char line[1024]; + + while (fgets(line, sizeof(line), stdin)) { + if (line[strlen(line)-1] == '\n') { + line[strlen(line)-1] = '\0'; + } + + double timestamp = 0; + int index = 0; + if (sscanf(line, "%lf %n", ×tamp, &index) < 1) { + goto bad; + } + + char *hex = line + index; + + static struct modesMessage mmZero; + struct modesMessage mm = mmZero; + for (unsigned i = 0; i < sizeof(mm.MB); ++i) { + if (!isxdigit(hex[i*2]) || !isxdigit(hex[i*2 + 1])) { + goto bad; + } + + unsigned xvalue = 0; + if (sscanf(hex + i*2, "%2x", &xvalue) < 1) { + goto bad; + } + + mm.MB[i] = xvalue; + } + + process(timestamp, line, &mm); + continue; + + bad: + fprintf(stderr, "failed to scan line: %s", line); + continue; + } +} diff --git a/oneoff/extract-comm-b.py b/oneoff/extract-comm-b.py new file mode 100755 index 0000000..6395b46 --- /dev/null +++ b/oneoff/extract-comm-b.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +# Run me like this: +# view1090 --no-interactive | ./extract-comm-b.py + +import re, sys, time +from contextlib import closing + +commb_match = re.compile(r'^DF:\d+ addr:([a-zA-Z0-9]{6}) FS:\d+ DR:\d+ UM:\d+ (?:ID|AC):\d+ MB:([a-zA-Z0-9]{14})$') + +for line in sys.stdin: + match = commb_match.match(line) + if match: + addr, mb = match.groups() + + with closing(open('commb/' + addr.upper() + '.txt', 'a')) as f: + print('%.3f %s' % (time.time(), mb), file=f)