QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
ADSBTCPLink.cc
Go to the documentation of this file.
1#include "ADSBTCPLink.h"
2// #include "QGCSensors.h"
4
5#include <QtNetwork/QTcpSocket>
6
7QGC_LOGGING_CATEGORY(ADSBTCPLinkLog, "ADSB.ADSBTCPLink")
8
9ADSBTCPLink::ADSBTCPLink(const QString &hostAddress, quint16 port, QObject *parent)
10 : QObject(parent)
11 , _hostAddress(hostAddress)
12 , _port(port)
13 , _socket(new QTcpSocket(this))
14{
15 if (ADSBTCPLinkLog().isDebugEnabled()) {
16 (void) connect(_socket, &QTcpSocket::stateChanged, this, [](QTcpSocket::SocketState state) {
17 switch (state) {
18 case QTcpSocket::UnconnectedState:
19 qCDebug(ADSBTCPLinkLog) << "ADSB Socket disconnected";
20 break;
21 case QTcpSocket::SocketState::ConnectingState:
22 qCDebug(ADSBTCPLinkLog) << "ADSB Socket connecting...";
23 break;
24 case QTcpSocket::SocketState::ConnectedState:
25 qCDebug(ADSBTCPLinkLog) << "ADSB Socket connected";
26 break;
27 case QTcpSocket::SocketState::ClosingState:
28 qCDebug(ADSBTCPLinkLog) << "ADSB Socket closing...";
29 break;
30 default:
31 break;
32 }
33 }, Qt::AutoConnection);
34 }
35
36 (void) QObject::connect(_socket, &QTcpSocket::errorOccurred, this, [this](QTcpSocket::SocketError error) {
37 qCDebug(ADSBTCPLinkLog) << error << _socket->errorString();
38 // TODO: Check if it is a critical error or not and send if the socket is stopped/recoverable
39 emit errorOccurred(_socket->errorString(), false);
40 }, Qt::AutoConnection);
41
42 (void) connect(_socket, &QTcpSocket::readyRead, this, &ADSBTCPLink::_readBytes);
43
44 // qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
45}
46
48{
49 // qCDebug(ADSBTCPLinkLog) << Q_FUNC_INFO << this;
50}
51
53{
54 /* if (!QGCDeviceInfo::isInternetAvailable()) {
55 return false;
56 } */
57
58 if (_hostAddress.isEmpty()) {
59 return false;
60 }
61
62 // connectToHost with a hostname resolves DNS asynchronously
63 _socket->connectToHost(_hostAddress, _port);
64
65 return true;
66}
67
68void ADSBTCPLink::_readBytes()
69{
70 while (_socket && _socket->canReadLine()) {
71 const QByteArray bytes = _socket->readLine();
72 _parseLine(QString::fromLocal8Bit(bytes));
73 }
74}
75
76void ADSBTCPLink::_parseLine(const QString &line)
77{
78 if (line.size() <= 4) {
79 return;
80 }
81
82 if (!line.startsWith(QStringLiteral("MSG"))) {
83 return;
84 }
85
86 const int msgType = line.at(4).digitValue();
87 if (msgType == ADSB::Unsupported) {
88 qCDebug(ADSBTCPLinkLog) << "ADSB Invalid message type" << msgType;
89 return;
90 }
91
92 // Skip unsupported mesg types to avoid parsing
93 if ((msgType == ADSB::SurfacePosition) || (msgType > ADSB::SurveillanceId)) {
94 return;
95 }
96
97 qCDebug(ADSBTCPLinkLog) << "ADSB SBS-1" << line;
98
99 const QStringList values = line.split(QChar(','));
100 if (values.size() <= 4) {
101 return;
102 }
103
104 bool icaoOk;
105 const uint32_t icaoAddress = values.at(4).toUInt(&icaoOk, 16);
106 if (!icaoOk) {
107 return;
108 }
109
110 ADSB::VehicleInfo_t adsbInfo;
111 adsbInfo.icaoAddress = icaoAddress;
112
113 switch (msgType) {
117 _parseAndEmitCallsign(adsbInfo, values);
118 break;
120 _parseAndEmitLocation(adsbInfo, values);
121 break;
123 _parseAndEmitHeading(adsbInfo, values);
124 break;
125 default:
126 break;
127 }
128}
129
130void ADSBTCPLink::_parseAndEmitCallsign(ADSB::VehicleInfo_t &adsbInfo, const QStringList &values)
131{
132 if (values.size() <= 10) {
133 return;
134 }
135
136 const QString callsign = values.at(10).trimmed();
137 if (callsign.isEmpty()) {
138 return;
139 }
140
141 adsbInfo.callsign = callsign;
143
144 emit adsbVehicleUpdate(adsbInfo);
145}
146
147void ADSBTCPLink::_parseAndEmitLocation(ADSB::VehicleInfo_t &adsbInfo, const QStringList &values)
148{
149 if (values.size() <= 19) {
150 return;
151 }
152
153 // Altitude is either Barometric - based on pressure, in ft
154 // or HAE - as reported by GPS - based on WGS84 Ellipsoid, in ft
155 // If altitude ends with H, we have HAE
156 // There's a slight difference between Barometric alt and HAE, but it would require
157 // knowledge about Geoid shape in particular Lat, Lon. It's not worth complicating the code
158 QString altitudeStr = values.at(11);
159 if (altitudeStr.endsWith('H')) {
160 (void) altitudeStr.chop(1);
161 }
162
163 bool altOk, latOk, lonOk, alertOk;
164 const int modeCAltitude = altitudeStr.toInt(&altOk);
165 const double lat = values.at(14).toDouble(&latOk);
166 const double lon = values.at(15).toDouble(&lonOk);
167 const int alert = values.at(19).toInt(&alertOk);
168
169 if (!altOk || !latOk || !lonOk || !alertOk) {
170 return;
171 }
172
173 if (qFuzzyIsNull(lat) && qFuzzyIsNull(lon)) {
174 return;
175 }
176
177 const double altitude = modeCAltitude * 0.3048;
178 const QGeoCoordinate location(lat, lon, altitude);
179
180 adsbInfo.location = location;
181 adsbInfo.alert = (alert == 1);
183
184 emit adsbVehicleUpdate(adsbInfo);
185}
186
187void ADSBTCPLink::_parseAndEmitHeading(ADSB::VehicleInfo_t &adsbInfo, const QStringList &values)
188{
189 if (values.size() <= 13) {
190 return;
191 }
192
193 bool headingOk = false, speedOk = false;
194 const double heading = values.at(13).toDouble(&headingOk);
195 const double speedKnots = values.at(12).toDouble(&speedOk);
196 if (!headingOk || !speedOk) {
197 return;
198 }
199
200 adsbInfo.heading = heading;
201 adsbInfo.velocity = speedKnots * 0.514444;
203
204 if (values.size() > 16) {
205 bool vertOk = false;
206 const double verticalRate = values.at(16).toDouble(&vertOk);
207 if (vertOk) {
208 adsbInfo.verticalVel = verticalRate * 0.00508;
210 }
211 }
212
213 emit adsbVehicleUpdate(adsbInfo);
214}
Error error
#define QGC_LOGGING_CATEGORY(name, categoryStr)
@ Unsupported
Definition ADSB.h:28
@ SurfacePosition
Definition ADSB.h:23
@ AirborneVelocity
Definition ADSB.h:25
@ AirbornePosition
Definition ADSB.h:24
@ IdentificationAndCategory
Definition ADSB.h:22
@ SurveillanceId
Definition ADSB.h:27
@ SurveillanceAltitude
Definition ADSB.h:26
@ AlertAvailable
Definition ADSB.h:41
@ VelocityAvailable
Definition ADSB.h:37
@ CallsignAvailable
Definition ADSB.h:38
@ AltitudeAvailable
Definition ADSB.h:35
@ LocationAvailable
Definition ADSB.h:34
@ VerticalVelAvailable
Definition ADSB.h:40
@ HeadingAvailable
Definition ADSB.h:36
uint32_t icaoAddress
Definition ADSB.h:49
double velocity
Definition ADSB.h:54
AvailableInfoTypes availableFlags
Definition ADSB.h:48
double verticalVel
Definition ADSB.h:55
double heading
Definition ADSB.h:52
QString callsign
Definition ADSB.h:50
QGeoCoordinate location
Definition ADSB.h:51