-
Notifications
You must be signed in to change notification settings - Fork 78
/
track.h
772 lines (647 loc) · 24.4 KB
/
track.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
// Part of readsb, a Mode-S/ADSB/TIS message decoder.
//
// track.h: aircraft state tracking prototypes
//
// Copyright (c) 2019 Michael Wolf <michael@mictronics.de>
//
// This code is based on a detached fork of dump1090-fa.
//
// Copyright (c) 2014-2016 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// This file incorporates work covered by the following copyright and
// license:
//
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DUMP1090_TRACK_H
#define DUMP1090_TRACK_H
/* Minimum number of repeated Mode A/C replies with a particular Mode A code needed in a
* 1 second period before accepting that code.
*/
#define TRACK_MODEAC_MIN_MESSAGES 4
/* Special value for Rc unknown */
#define RC_UNKNOWN 0
#define ALTITUDE_BARO_RELIABLE_MAX 20
#define POS_RELIABLE_TIMEOUT (60 * MINUTES)
#define TRACK_STALE (15*SECONDS)
#define TRACK_EXPIRE (60*SECONDS)
#define TRACK_EXPIRE_LONG (180*SECONDS)
#define TRACK_EXPIRE_JAERO (33*MINUTES)
#define TRACK_EXPIRE_ROUGH (2 * MINUTES)
#define NOGPS_DWELL (15 * MINUTES)
#define NOGPS_MAX (20)
#define NOGPS_SHOW (17)
int nogps(int64_t now, struct aircraft *a);
// 2.5 seconds maximum between messages used for calculating wind / temperature
#define TRACK_WT_TIMEOUT (2500)
#define RECEIVERIDBUFFER (12)
#ifndef RECENT_RECEIVER_IDS
#define RECENT_RECEIVER_IDS (32)
#endif
typedef struct
{
uint64_t id;
int64_t time;
} idTime;
#define DISCARD_CACHE (4)
#define CPR_CACHE (4)
typedef enum
{
REDUCE_RARE,
REDUCE_OFTEN,
} reduce_freq_t;
// data moves through three states:
// fresh: data is valid. Updates from a less reliable source are not accepted.
// stale: data is valid. Updates from a less reliable source are accepted.
// expired: data is not valid.
typedef struct
{
int64_t updated; /* when it arrived */
int64_t next_reduce_forward; /* when to next forward the data for reduced beast output */
datasource_t source:8; /* where the data came from */
datasource_t last_source:8; /* where the data came from */
int8_t stale; /* if it's stale 1 / 0 */
unsigned padding:8;
int padding2;
} data_validity;
// size must be multiple of 64 bits so it can be aligned in struct aircraft.
// uint16: 0 to 65535
#define _gs_factor (10.0f) // 6000 to 60000
#define _track_factor (100.0f) // 360 -> 36000
// int16: -32768 to 32767
#define _alt_factor (1/6.25f) // 200000 to 32000
#define _rate_factor (1/8.0f) // 262136 to 32767
#define _roll_factor (100.0f) // 180 to 18000
/* Structure representing one point in the aircraft trace */
struct state
{
int64_t timestamp:48;
//struct state_flags flags; // 16 bits
unsigned on_ground:1;
unsigned stale:1;
unsigned leg_marker:1;
unsigned gs_valid:1;
unsigned track_valid:1;
unsigned baro_alt_valid:1;
unsigned baro_rate_valid:1;
unsigned geom_alt_valid:1;
unsigned geom_rate_valid:1;
unsigned roll_valid:1;
unsigned ias_valid:1;
unsigned padding:5;
int32_t lat;
int32_t lon;
uint16_t gs;
uint16_t track;
int16_t baro_alt;
int16_t baro_rate;
int16_t geom_alt;
int16_t geom_rate;
unsigned ias:12;
int roll:12;
addrtype_t addrtype:5;
int padding2:3;
#if defined(TRACKS_UUID)
uint32_t receiverId;
#endif
} __attribute__ ((__packed__));
struct state_all
{
char callsign[8]; // Flight number
uint16_t squawk; // Squawk
int16_t nav_altitude_mcp; // FCU/MCP selected altitude
int16_t nav_altitude_fms; // FMS selected altitude
int16_t nav_qnh; // Altimeter setting (QNH/QFE), millibars
uint16_t nav_heading; // target heading, degrees (0-359)
uint16_t mach;
int16_t track_rate; // Rate of change of ground track, degrees/second
uint16_t mag_heading; // Magnetic heading
uint16_t true_heading; // True heading
int wind_direction:10;
int wind_speed:10;
int oat:10;
int tat:10;
unsigned category:8; // Aircraft category A0 - D7 encoded as a single hex byte. 00 = unset
unsigned pos_nic:8; // NIC of last computed position
unsigned pos_rc:16; // Rc of last computed position
emergency_t emergency:3; // Emergency/priority status
nav_modes_t nav_modes:7; // enabled modes (autopilot, vnav, etc)
airground_t airground:2; // air/ground status
nav_altitude_source_t nav_altitude_src:3; // source of altitude used by automation
sil_type_t sil_type:3; // SIL supplement from TSS or opstatus
unsigned tas:12;
unsigned adsb_version:4; // ADS-B version (from ADS-B operational status); -1 means no ADS-B messages seen
unsigned adsr_version:4; // As above, for ADS-R messages
unsigned tisb_version:4; // As above, for TIS-B messages
unsigned nic_a : 1; // NIC supplement A from opstatus
unsigned nic_c : 1; // NIC supplement C from opstatus
unsigned nic_baro : 1; // NIC baro supplement from TSS or opstatus
unsigned nac_p : 4; // NACp from TSS or opstatus
unsigned nac_v : 3; // NACv from airborne velocity or opstatus
unsigned sil : 2; // SIL from TSS or opstatus
unsigned gva : 2; // GVA from opstatus
unsigned sda : 2; // SDA from opstatus
unsigned alert : 1; // FS Flight status alert bit
unsigned spi : 1; // FS Flight status SPI (Special Position Identification) bit
unsigned callsign_valid:1;
unsigned tas_valid:1;
unsigned mach_valid:1;
unsigned track_valid:1;
unsigned track_rate_valid:1;
unsigned mag_heading_valid:1;
unsigned true_heading_valid:1;
unsigned nic_a_valid:1;
unsigned nic_c_valid:1;
unsigned nic_baro_valid:1;
unsigned nac_p_valid:1;
unsigned nac_v_valid:1;
unsigned sil_valid:1;
unsigned gva_valid:1;
unsigned sda_valid:1;
unsigned squawk_valid:1;
unsigned emergency_valid:1;
unsigned airground_valid:1;
unsigned nav_qnh_valid:1;
unsigned nav_altitude_mcp_valid:1;
unsigned nav_altitude_fms_valid:1;
unsigned nav_altitude_src_valid:1;
unsigned nav_heading_valid:1;
unsigned nav_modes_valid:1;
unsigned position_valid:1; // used for position accuracy stuff, position is in small state struct
unsigned alert_valid:1;
unsigned spi_valid:1;
unsigned wind_valid:1;
unsigned temp_valid:1;
} __attribute__ ((__packed__));
#define SFOUR (4)
typedef struct fourState {
struct state no[SFOUR];
struct state_all zeroAll;
} fourState;
typedef struct traceBuffer {
int len;
fourState *trace;
} traceBuffer;
static inline int getFourStates(int points) {
return ((points + SFOUR - 1) / SFOUR);
}
static inline int alignSFOUR(int value) {
return ((value + SFOUR - 1) / SFOUR) * SFOUR;
}
static inline ssize_t stateBytes(int points) {
return getFourStates(points) * sizeof(fourState);
}
static inline struct state *getState(fourState *buffer, int position) {
return &buffer[position / SFOUR].no[position % SFOUR];
}
static inline struct state_all *getStateAll(fourState *buffer, int position) {
if (position % SFOUR == 0)
return &buffer[position / SFOUR].zeroAll;
else
return NULL;
}
typedef struct stateChunk {
unsigned char *compressed;
int compressed_size;
int numStates;
int64_t firstTimestamp;
int64_t lastTimestamp;
} stateChunk;
struct cpr_cache {
uint32_t cpr_lat;
uint32_t cpr_lon;
int64_t ts;
uint64_t receiverId;
};
struct traceCacheEntry {
int64_t ts;
int32_t offset;
int32_t len;
int32_t leg_marker;
};
struct traceCache {
int32_t entriesLen;
int32_t json_max;
int32_t firstRecentCache;
int32_t totalAlloc;
int64_t referenceTs;
struct traceCacheEntry *entries;
char *json;
};
/* Structure used to describe the state of one tracked aircraft */
struct aircraft
{
struct aircraft *next; // Next aircraft in our linked list
uint32_t addr; // ICAO address
addrtype_t addrtype; // highest priority address type seen for this aircraft
int64_t seen; // Time (millis) at which the last packet with reliable address was received
int64_t seen_pos; // Time (millis) at which the last position was received
uint32_t messages; // Number of Mode S messages received
int32_t onActiveList;
uint32_t receiverCount;
uint32_t category; // Aircraft category A0 - D7 encoded as a single hex byte. 00 = unset
//
int64_t category_updated;
// ----
int64_t trace_next_mw; // timestamp for next full trace write to /run (tmpfs)
int64_t trace_next_perm; // timestamp for next trace write to history_dir (disk)
int64_t lastSignalTimestamp; // timestamp the last message with RSSI was received
int64_t trace_perm_last_timestamp; // timestamp for last trace point written to disk
fourState *trace_current; // uncompressed most recent points in the trace
stateChunk *trace_chunks; // compressed chunks of trace
int32_t trace_current_max;
int32_t trace_current_len; // number of points in our uncompressed most recent trace portion
int32_t trace_len; // total number of points in the trace
int32_t trace_chunk_len; // how many stateChunks are saved for this aircraft
int32_t trace_write; // signal for writing the trace
int32_t trace_writeCounter; // how many points where added since the complete trace was written to memory
int32_t baro_alt; // Altitude (Baro)
int32_t alt_reliable;
int32_t geom_alt; // Altitude (Geometric)
int32_t geom_delta; // Difference between Geometric and Baro altitudes
uint32_t signalNext; // next index of signalLevel to use
// ----
double signalLevel[8]; // Last 8 Signal Amplitudes
// ----
float rr_lat; // very rough receiver latitude
float rr_lon; // very rough receiver longitude
int64_t rr_seen; // when we noted this rough position
int64_t seenAdsbReliable; // last time we saw a reliable SOURCE_ADSB positions from this aircraft
int64_t addrtype_updated;
float tat;
uint16_t nogpsCounter;
uint16_t receiverIdsNext;
int64_t seenPosReliable; // last time we saw a reliable position
uint64_t lastPosReceiverId;
// ---- the following section has 9 instead of 8 times 8 bytes. but that's not critical as long as the 8 byte alignment is ok
uint32_t pos_nic; // NIC of last computed position
uint32_t pos_rc; // Rc of last computed position
double lat; // Coordinates obtained from CPR encoded data
double lon; // Coordinates obtained from CPR encoded data
float pos_reliable_odd; // Number of good global CPRs, indicates position reliability
float pos_reliable_even;
int16_t traceWrittenForYesterday; // the permanent trace has been written for the previous day
uint16_t mlatEPU;
float gs_last_pos; // Save a groundspeed associated with the last position
float wind_speed;
float wind_direction;
int32_t wind_altitude;
float oat;
int64_t wind_updated;
int64_t oat_updated;
int64_t tat_updated;
// ----
int32_t baro_rate; // Vertical rate (barometric)
int32_t geom_rate; // Vertical rate (geometric)
uint32_t ias;
uint32_t tas;
uint32_t squawk; // Squawk
uint32_t squawkTentative; // require the same squawk code twice to accept it
uint32_t nav_altitude_mcp; // FCU/MCP selected altitude
uint32_t nav_altitude_fms; // FMS selected altitude
uint32_t cpr_odd_lat;
uint32_t cpr_odd_lon;
uint32_t cpr_odd_nic;
uint32_t cpr_odd_rc;
uint32_t cpr_even_lat;
uint32_t cpr_even_lon;
uint32_t cpr_even_nic;
uint32_t cpr_even_rc;
// ----
float nav_qnh; // Altimeter setting (QNH/QFE), millibars
float nav_heading; // target heading, degrees (0-359)
float gs;
float mach;
float track; // Ground track
float track_rate; // Rate of change of ground track, degrees/second
float roll; // Roll angle, degrees right
float mag_heading; // Magnetic heading
float true_heading; // True heading
float calc_track; // Calculated Ground track
int64_t next_reduce_forward_DF11;
char callsign[16]; // Flight number
// ----
emergency_t emergency; // Emergency/priority status
airground_t airground; // air/ground status
nav_modes_t nav_modes; // enabled modes (autopilot, vnav, etc)
cpr_type_t cpr_odd_type;
cpr_type_t cpr_even_type;
nav_altitude_source_t nav_altitude_src; // source of altitude used by automation
int32_t modeA_hit; // did our squawk match a possible mode A reply in the last check period?
int32_t modeC_hit; // did our altitude match a possible mode C reply in the last check period?
// data extracted from opstatus etc
int32_t adsb_version; // ADS-B version (from ADS-B operational status); -1 means no ADS-B messages seen
int32_t adsr_version; // As above, for ADS-R messages
int32_t tisb_version; // As above, for TIS-B messages
heading_type_t adsb_hrd; // Heading Reference Direction setting (from ADS-B operational status)
heading_type_t adsb_tah; // Track Angle / Heading setting (from ADS-B operational status)
int32_t globe_index; // custom index of the planes area on the globe
sil_type_t sil_type; // SIL supplement from TSS or opstatus
uint32_t nic_a : 1; // nic supplement a from opstatus
uint32_t nic_c : 1; // nic supplement c from opstatus
uint32_t nic_baro : 1; // nic baro supplement from tss or opstatus
uint32_t nac_p : 4; // nacp from tss or opstatus
uint32_t nac_v : 3; // nacv from airborne velocity or opstatus
uint32_t sil : 2; // sil from tss or opstatus
uint32_t gva : 2; // gva from opstatus
uint32_t sda : 2; // sda from opstatus
// 16 bit
uint32_t alert : 1; // fs flight status alert bit
uint32_t spi : 1; // fs flight status spi (special position identification) bit
uint32_t pos_surface : 1; // (a->airground == ag_ground) associated with current position
uint32_t last_cpr_type : 2; // mm->cpr_type associated with current position
uint32_t tracePosBuffered : 1; // denotes if a->trace[a->trace_len] has a valid state buffered in it
uint32_t surfaceCPR_allow_ac_rel : 1; // allow surface cpr relative to last known aircraft location
uint32_t localCPR_allow_ac_rel : 1; // allow local cpr relative to last known aircraft location
// 24 bit
uint32_t last_message_crc_fixed : 1;
uint32_t is_df18_exception : 1;
uint32_t padding_b : 6;
// 32 bit !!
// ----
data_validity callsign_valid;
data_validity baro_alt_valid;
data_validity geom_alt_valid;
data_validity geom_delta_valid;
data_validity gs_valid;
data_validity ias_valid;
data_validity tas_valid;
data_validity mach_valid;
data_validity track_valid;
data_validity track_rate_valid;
data_validity roll_valid;
data_validity mag_heading_valid;
data_validity true_heading_valid;
data_validity baro_rate_valid;
data_validity geom_rate_valid;
data_validity nic_a_valid;
data_validity nic_c_valid;
data_validity nic_baro_valid;
data_validity nac_p_valid;
data_validity nac_v_valid;
data_validity sil_valid;
data_validity gva_valid;
data_validity sda_valid;
data_validity squawk_valid;
data_validity emergency_valid;
data_validity airground_valid;
data_validity nav_qnh_valid;
data_validity nav_altitude_mcp_valid;
data_validity nav_altitude_fms_valid;
data_validity nav_altitude_src_valid;
data_validity nav_heading_valid;
data_validity nav_modes_valid;
data_validity cpr_odd_valid; // Last seen even CPR message
data_validity cpr_even_valid; // Last seen odd CPR message
data_validity position_valid;
data_validity alert_valid;
data_validity spi_valid;
int64_t seenPosGlobal; // seen global CPR or other hopefully reliable position
double latReliable; // last reliable position based on json_reliable threshold
double lonReliable; // last reliable position based on json_reliable threshold
char typeCode[4];
char registration[12];
char typeLong[64];
uint16_t receiverIds[RECEIVERIDBUFFER]; // RECEIVERIDBUFFER = 12
int64_t next_reduce_forward_status;
unsigned char acas_ra[7]; // mm->MV from last acas RA message
unsigned char acas_flags; // maybe use for some flags, would be padding otherwise
data_validity acas_ra_valid;
float gs_reliable;
float track_reliable;
uint64_t canary1;
int64_t squawkTentativeChanged;
double magneticDeclination;
int64_t updatedDeclination;
uint16_t pos_nic_reliable;
uint16_t pos_rc_reliable;
int32_t trackUnreliable;
uint64_t receiverId;
// previous position and timestamp
double prev_lat; // previous latitude
double prev_lon; // previous longitude
int64_t prev_pos_time; // time the previous position was received
int32_t speedUnreliable;
uint32_t lastStatusDiscarded;
int64_t nextJsonPortOutput;
float receiver_distance;
float receiver_direction;
data_validity mlat_pos_valid;
double mlat_lat;
double mlat_lon;
data_validity pos_reliable_valid;
// last reliable SOURCE_ADSB positions from this aircraft
double seenAdsbLat;
double seenAdsbLon;
int64_t lastStatusTs;
int64_t lastOverrideTs;
// DANGER, this section is zeroed when saving and loading data
char zeroStart;
char ownOp[64];
char year[4];
uint16_t dbFlags;
float messageRate;
uint16_t messageRateAcc[MESSAGE_RATE_CALC_POINTS];
int64_t nextMessageRateCalc;
uint32_t disc_cache_index;
uint32_t cpr_cache_index;
struct cpr_cache disc_cache[DISCARD_CACHE];
struct cpr_cache cpr_cache[CPR_CACHE];
// keep trace cache after cpr / disc cache
// stuff above is put into
struct traceCache traceCache;
uint32_t trace_chunk_overall_bytes;
int8_t initialTraceWriteDone;
#if defined(PRINT_UUIDS)
int recentReceiverIdsNext;
idTime recentReceiverIds[RECENT_RECEIVER_IDS];
#endif
char zeroEnd;
};
/* Mode A/C tracking is done separately, not via the aircraft list,
* and via a flat array rather than a list since there are only 4k possible values
* (nb: we ignore the ident/SPI bit when tracking)
*/
extern uint32_t modeAC_count[4096];
extern uint32_t modeAC_match[4096];
extern uint32_t modeAC_age[4096];
/* is this bit of data valid? */
static inline void
updateValidity (data_validity *v, int64_t now, int64_t expiration_timeout)
{
if (v->source == SOURCE_INVALID)
return;
int stale = (now > v->updated + TRACK_STALE);
if (stale != v->stale)
v->stale = stale;
if (v->source == SOURCE_JAERO) {
if (now > v->updated + Modes.trackExpireJaero)
v->source = SOURCE_INVALID;
} else if (v->source == SOURCE_INDIRECT && Modes.debug_rough_receiver_location) {
if (now > v->updated + TRACK_EXPIRE_ROUGH)
v->source = SOURCE_INVALID;
} else {
if (now > v->updated + expiration_timeout)
v->source = SOURCE_INVALID;
}
}
/* is this bit of data valid? */
static inline int
trackDataValid (const data_validity *v)
{
return (v->source != SOURCE_INVALID);
}
static inline int posReliable(struct aircraft *a) {
if (!trackDataValid(&a->position_valid)) {
return 0;
}
if (a->position_valid.source == SOURCE_JAERO
|| a->position_valid.source == SOURCE_MLAT
|| a->position_valid.source == SOURCE_INDIRECT) {
return 1;
}
int reliable = Modes.json_reliable;
// disable this extra requirement for the moment:
if (0 && Modes.position_persistence > reliable && reliable > 1 && (a->addr & MODES_NON_ICAO_ADDRESS || a->addrtype == ADDR_TISB_ICAO || a->addrtype == ADDR_ADSR_ICAO)) {
reliable += 1; // require additional reliability for non-icao hex addresses
}
if (a->pos_reliable_odd >= reliable && a->pos_reliable_even >= reliable) {
return 1;
}
return 0;
}
static inline int altBaroReliable(struct aircraft *a) {
if (!trackDataValid(&a->baro_alt_valid))
return 0;
if (a->position_valid.source == SOURCE_JAERO)
return 1;
if (a->alt_reliable >= 2 * Modes.json_reliable)
return 1;
return 0;
}
static inline int
trackVState (int64_t now, const data_validity *v, const data_validity *pos_valid)
{
if (pos_valid->source <= SOURCE_JAERO) {
// allow normal expiration time for shitty position sources
return (v->source != SOURCE_INVALID);
}
// reduced expiration time for good sources
return (v->source != SOURCE_INVALID && now < v->updated + 35 * SECONDS);
}
static inline int altBaroReliableTrace(int64_t now, struct aircraft *a) {
if (altBaroReliable(a) && trackVState(now, &a->baro_alt_valid, &a->pos_reliable_valid))
return 1;
else
return 0;
}
/* what's the age of this data, in milliseconds? */
static inline int64_t
trackDataAge (int64_t now, const data_validity *v)
{
if (v->updated >= now)
return 0;
return (now - v->updated);
}
static inline double toRad(double degrees) {
return degrees * (M_PI / 180.0);
}
static inline double toDeg(double radians) {
return radians * (180.0 / M_PI);
}
// calculate great circle distance in meters
//
void to_state(struct aircraft *a, struct state *new, int64_t now, int on_ground, float track, int stale);
void to_state_all(struct aircraft *a, struct state_all *new, int64_t now);
void from_state_all(struct state_all *in, struct state *in2, struct aircraft *a , int64_t ts);
/* Update aircraft state from data in the provided mesage.
* Return the tracked aircraft.
*/
struct modesMessage;
struct aircraft *trackUpdateFromMessage (struct modesMessage *mm);
void trackMatchAC(int64_t now);
void trackRemoveStale(int64_t now);
void updateValidities(struct aircraft *a, int64_t now);
struct aircraft *trackFindAircraft(uint32_t addr);
/* Convert from a (hex) mode A value to a 0-4095 index */
static inline unsigned
modeAToIndex (unsigned modeA)
{
return (modeA & 0x0007) | ((modeA & 0x0070) >> 1) | ((modeA & 0x0700) >> 2) | ((modeA & 0x7000) >> 3);
}
/* Convert from a 0-4095 index to a (hex) mode A value */
static inline unsigned
indexToModeA (unsigned index)
{
return (index & 0007) | ((index & 0070) << 1) | ((index & 0700) << 2) | ((index & 07000) << 3);
}
/* convert from (hex) squawk to (dec) squawk */
static inline uint32_t squawkHex2Dec(uint32_t s) {
return ( (s & 0xf000) / 0x1000 * 1000 + (s & 0x0f00) / 0x100 * 100 + (s & 0x00f0) / 0x10 * 10 + (s & 0x000f) / 0x1 * 1);
}
/* convert from (dec) squawk to (hex) squawk */
static inline uint32_t squawkDec2Hex(uint32_t s) {
return ( (s / 1000 % 10) * 16*16*16 + (s / 100 % 10) * 16*16 + (s / 10 % 10) * 16 + (s % 10) );
}
static inline int bogus_lat_lon(double lat, double lon) {
if (fabs(lat) >= 90.0 || fabs(lon) >= 180.0)
return 1;
if (lat == 0 && (lon == -90 || lon == 90 || lon == 0))
return 1;
if (fabs(lat) < 0.01 && fabs(lon) < 0.01)
return 1;
return 0;
}
static inline int get8bitSignal(struct aircraft *a) {
double signal = (a->signalLevel[0] + a->signalLevel[1] + a->signalLevel[2] + a->signalLevel[3] +
a->signalLevel[4] + a->signalLevel[5] + a->signalLevel[6] + a->signalLevel[7]) / 8.0;
signal = sqrt(signal) * 255.0;
if (signal > 255) signal = 255;
if (signal < 1 && signal > 0) signal = 1;
return (int) nearbyint(signal);
}
static inline const char *nonIcaoSpace(struct aircraft *a) {
if (a->addr & MODES_NON_ICAO_ADDRESS) {
return "";
} else {
return " ";
}
}
#endif