1+ #include " ADSB.h"
2+ #include " Stream.h"
3+
4+ class PlaneDB : public StreamIn <Plane::ADSB>
5+ {
6+ std::mutex mtx;
7+ private:
8+ int first = -1 ;
9+ int last = -1 ;
10+ int count = 0 ;
11+ std::vector<Plane::ADSB> items;
12+ int N = 512 ;
13+ public:
14+ PlaneDB () {
15+ items.resize (N);
16+
17+ first = N - 1 ;
18+ last = 0 ;
19+ count = 0 ;
20+
21+ // set up linked list
22+ for (int i = 0 ; i < N; i++)
23+ {
24+ items[i].next = i - 1 ;
25+ items[i].prev = i + 1 ;
26+ }
27+ items[N - 1 ].prev = -1 ;
28+ }
29+
30+ void moveToFront (int ptr) {
31+ if (ptr == first)
32+ return ;
33+
34+ // remove ptr out of the linked list
35+ if (items[ptr].next != -1 )
36+ items[items[ptr].next ].prev = items[ptr].prev ;
37+ else
38+ last = items[ptr].prev ;
39+
40+ items[items[ptr].prev ].next = items[ptr].next ;
41+
42+ // new ship is first in list
43+ items[ptr].next = first;
44+ items[ptr].prev = -1 ;
45+
46+ items[first].prev = ptr;
47+ first = ptr;
48+ }
49+
50+ int create () {
51+ int ptr = last;
52+ count = MIN (count + 1 , N);
53+ items[ptr].clear ();
54+
55+ return ptr;
56+ }
57+
58+ int find (int hexid) const {
59+ int ptr = first, cnt = count;
60+ while (ptr != -1 && --cnt >= 0 )
61+ {
62+ if (items[ptr].hexident == hexid)
63+ return ptr;
64+ ptr = items[ptr].next ;
65+ }
66+ return -1 ;
67+ }
68+
69+ void Receive (const Plane::ADSB* msg, int len, TAG& tag) {
70+ std::lock_guard<std::mutex> lock (mtx);
71+
72+ // Skip invalid messages
73+ if (msg->getHexIdent () == 0 ) return ;
74+
75+ // Find or create plane entry
76+ int ptr = find (msg->getHexIdent ());
77+ if (ptr == -1 ) {
78+ ptr = create ();
79+ }
80+
81+ // Move to front and update data
82+ moveToFront (ptr);
83+ Plane::ADSB& plane = items[ptr];
84+
85+ // Update timestamp and core identifiers
86+ plane.setRxTimeUnix (msg->getRxTimeUnix ());
87+ plane.setHexIdent (msg->getHexIdent ());
88+
89+ // Update position if valid
90+ if (msg->getLat () != LAT_UNDEFINED && msg->getLon () != LON_UNDEFINED) {
91+ plane.setPosition (msg->getLat (), msg->getLon ());
92+ }
93+
94+ // Update altitude
95+ if (msg->getAltitude () != 0 ) {
96+ plane.setAltitude (msg->getAltitude ());
97+ }
98+
99+ // Update movement data
100+ if (msg->getGroundSpeed () != GROUNDSPEED_UNDEFINED) {
101+ plane.setGroundSpeed (msg->getGroundSpeed ());
102+ }
103+ if (msg->getTrack () != TRACK_UNDEFINED) {
104+ plane.setTrack (msg->getTrack ());
105+ }
106+ if (msg->getVertRate () != VERTRATE_UNDEFINED) {
107+ plane.setVertRate (msg->getVertRate ());
108+ }
109+
110+ // Update identification
111+ if (msg->getSquawk () != SQUAWK_UNDEFINED) {
112+ plane.setSquawk (msg->getSquawk ());
113+ }
114+ if (msg->getCallsign () != " @@@@@@@@" ) {
115+ plane.setCallsign (msg->getCallsign ());
116+ }
117+
118+ // Update status flags
119+ if (msg->getAlert () != Plane::BoolType::UNKNOWN) {
120+ plane.setAlert (msg->getAlert ());
121+ }
122+ if (msg->getEmergency () != Plane::BoolType::UNKNOWN) {
123+ plane.setEmergency (msg->getEmergency ());
124+ }
125+ if (msg->getSPI () != Plane::BoolType::UNKNOWN) {
126+ plane.setSPI (msg->getSPI ());
127+ }
128+ if (msg->isOnGround () != Plane::BoolType::UNKNOWN) {
129+ plane.setOnGround (msg->isOnGround ());
130+ }
131+
132+ plane.setType (msg->getType ());
133+ plane.setTransmission (msg->getTransmission ());
134+
135+ if (msg->getLat () != LAT_UNDEFINED && msg->getLon () != LON_UNDEFINED) {
136+ tag.lat = msg->getLat ();
137+ tag.lon = msg->getLon ();
138+ }
139+ }
140+
141+ std::string getCompactArray (bool include_inactive = false ) {
142+ std::lock_guard<std::mutex> lock (mtx);
143+
144+ const std::string null_str = " null" ;
145+ const std::string comma = " ," ;
146+ std::string content = " {\" count\" :" + std::to_string (count) + " ,\" values\" :[" ;
147+
148+ std::time_t now = std::time (nullptr );
149+ int ptr = first;
150+ std::string delim = " " ;
151+
152+ while (ptr != -1 ) {
153+ const Plane::ADSB& plane = items[ptr];
154+
155+ if (plane.getHexIdent () != 0 ) {
156+ long int time_since_update = now - plane.getRxTimeUnix ();
157+
158+ // Skip inactive planes unless requested
159+ if (!include_inactive && time_since_update > 3600 ) {
160+ // break;
161+ }
162+
163+ content += delim + " [" +
164+ std::to_string (plane.getHexIdent ()) + comma +
165+ (plane.getLat () != LAT_UNDEFINED ? std::to_string (plane.getLat ()) : null_str) + comma +
166+ (plane.getLon () != LON_UNDEFINED ? std::to_string (plane.getLon ()) : null_str) + comma +
167+ (plane.getAltitude () != 0 ? std::to_string (plane.getAltitude ()) : null_str) + comma +
168+ (plane.getGroundSpeed () != GROUNDSPEED_UNDEFINED ? std::to_string (plane.getGroundSpeed ()) : null_str) + comma +
169+ (plane.getTrack () != TRACK_UNDEFINED ? std::to_string (plane.getTrack ()) : null_str) + comma +
170+ (plane.getVertRate () != VERTRATE_UNDEFINED ? std::to_string (plane.getVertRate ()) : null_str) + comma +
171+ (plane.getSquawk () != SQUAWK_UNDEFINED ? std::to_string (plane.getSquawk ()) : null_str) + comma +
172+ plane.getCallsign () + comma +
173+ (plane.getAlert () != Plane::BoolType::UNKNOWN ? std::to_string (static_cast <int >(plane.getAlert ())) : null_str) + comma +
174+ (plane.getEmergency () != Plane::BoolType::UNKNOWN ? std::to_string (static_cast <int >(plane.getEmergency ())) : null_str) + comma +
175+ (plane.getSPI () != Plane::BoolType::UNKNOWN ? std::to_string (static_cast <int >(plane.getSPI ())) : null_str) + comma +
176+ (plane.isOnGround () != Plane::BoolType::UNKNOWN ? std::to_string (static_cast <int >(plane.isOnGround ())) : null_str) + comma +
177+ std::to_string (static_cast <int >(plane.getType ())) + comma +
178+ std::to_string (static_cast <int >(plane.getTransmission ())) + comma +
179+ std::to_string (time_since_update) + " ]" ;
180+
181+ delim = comma;
182+ }
183+ ptr = items[ptr].next ;
184+ }
185+
186+ content += " ],\" error\" :false}\n\n " ;
187+ return content;
188+ }
189+
190+ int getFirst () const { return first; }
191+ int getLast () const { return last; }
192+ int getCount () const { return count; }
193+ };
0 commit comments