11#include <QtCore/QApplicationStatic>
12#include <QtCore/QThread>
13#include <QtCore/QTimer>
21 , _adsbSettings(settings)
22 , _adsbVehicleCleanupTimer(new QTimer(this))
27 (void) qRegisterMetaType<ADSB::VehicleInfo_t>(
"ADSB::VehicleInfo_t");
29 _adsbVehicleCleanupTimer->setSingleShot(
false);
30 _adsbVehicleCleanupTimer->setInterval(1000);
31 (void) connect(_adsbVehicleCleanupTimer, &QTimer::timeout,
this, &ADSBVehicleManager::_cleanupStaleVehicles);
33 _adsbVehicleCleanupTimer->start();
35 Fact*
const adsbEnabled = _adsbSettings->adsbServerConnectEnabled();
36 Fact*
const hostAddress = _adsbSettings->adsbServerHostAddress();
37 Fact*
const port = _adsbSettings->adsbServerPort();
47 if (adsbEnabled->
rawValue().toBool()) {
61 return _adsbVehicleManager();
66 if (message.msgid != MAVLINK_MSG_ID_ADSB_VEHICLE) {
70 _handleADSBVehicle(message);
75 mavlink_adsb_vehicle_t adsbVehicleMsg{};
76 mavlink_msg_adsb_vehicle_decode(&message, &adsbVehicleMsg);
78 if (adsbVehicleMsg.tslc > kMaxTimeSinceLastSeen) {
86 vehicleInfo.icaoAddress = adsbVehicleMsg.ICAO_address;
87 vehicleInfo.lastContact = adsbVehicleMsg.tslc;
89 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_COORDS) {
91 vehicleInfo.location.setLatitude(adsbVehicleMsg.lat / 1e7);
92 vehicleInfo.location.setLongitude(adsbVehicleMsg.lon / 1e7);
95 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_ALTITUDE) {
97 vehicleInfo.location.setAltitude(adsbVehicleMsg.altitude / 1e3);
100 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_HEADING) {
102 vehicleInfo.heading = adsbVehicleMsg.heading / 1e2;
105 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_VELOCITY) {
107 vehicleInfo.velocity = adsbVehicleMsg.hor_velocity / 1e2;
110 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_CALLSIGN) {
112 vehicleInfo.callsign = QString::fromLatin1(adsbVehicleMsg.callsign,
sizeof(adsbVehicleMsg.callsign));
115 if (adsbVehicleMsg.flags & ADSB_FLAGS_VALID_SQUAWK) {
117 vehicleInfo.squawk = adsbVehicleMsg.squawk;
120 if (adsbVehicleMsg.flags & ADSB_FLAGS_SIMULATED) {
121 vehicleInfo.simulated =
true;
124 if (adsbVehicleMsg.flags & ADSB_FLAGS_VERTICAL_VELOCITY_VALID) {
126 vehicleInfo.verticalVel = adsbVehicleMsg.ver_velocity;
129 if (adsbVehicleMsg.flags & ADSB_FLAGS_BARO_VALID) {
130 vehicleInfo.baro =
true;
133 if (adsbVehicleMsg.flags & ADSB_FLAGS_SOURCE_UAT) {
137 adsbVehicleMsg.altitude_type = adsbVehicleMsg.altitude_type;
138 adsbVehicleMsg.emitter_type = adsbVehicleMsg.emitter_type;
145 const uint32_t icaoAddress = vehicleInfo.
icaoAddress;
146 if (_adsbICAOMap.contains(icaoAddress)) {
147 _adsbICAOMap[icaoAddress]->update(vehicleInfo);
153 _adsbICAOMap[icaoAddress] = adsbVehicle;
154 _adsbVehicles->
append(adsbVehicle);
155 qCDebug(ADSBVehicleManagerLog) <<
"Added" << QString::number(adsbVehicle->
icaoAddress());
159void ADSBVehicleManager::_start(
const QString &hostAddress, quint16 port)
162 qCWarning(ADSBVehicleManagerLog) <<
"TCP Link already started";
166 if (hostAddress.isEmpty()) {
167 qCWarning(ADSBVehicleManagerLog) <<
"No ADSB server host address set";
174 _adsbTcpLinkThread =
new QThread();
175 _adsbTcpLinkThread->setObjectName(QStringLiteral(
"ADSBTCPLink"));
178 _adsbTcpLink->moveToThread(_adsbTcpLinkThread);
180 (void) connect(_adsbTcpLinkThread, &QThread::started, _adsbTcpLink, &
ADSBTCPLink::init);
181 (void) connect(_adsbTcpLinkThread, &QThread::finished, _adsbTcpLink, &QObject::deleteLater);
185 _adsbTcpLinkThread->start();
188void ADSBVehicleManager::_stop()
190 if (!_adsbTcpLinkThread) {
194 _adsbTcpLinkThread->quit();
195 if (!_adsbTcpLinkThread->wait(kThreadStopTimeoutMs)) {
198 qCWarning(ADSBVehicleManagerLog) <<
"ADSBTCPLink thread failed to stop";
203 delete _adsbTcpLinkThread;
204 _adsbTcpLinkThread =
nullptr;
205 _adsbTcpLink =
nullptr;
208 _adsbICAOMap.clear();
211void ADSBVehicleManager::_cleanupStaleVehicles()
213 for (qsizetype i = _adsbVehicles->
count() - 1; i >= 0; i--) {
216 qCDebug(ADSBVehicleManagerLog) <<
"Expired" << QString::number(adsbVehicle->
icaoAddress());
218 (void) _adsbICAOMap.remove(adsbVehicle->
icaoAddress());
219 adsbVehicle->deleteLater();
224void ADSBVehicleManager::_linkError(
const QString &errorMsg,
bool stopped)
226 qCDebug(ADSBVehicleManagerLog) << errorMsg;
228 QString msg = QStringLiteral(
"ADSB Server Error: %1").arg(errorMsg);
231 (void) msg.append(
"\nADSB has been disabled");
232 _adsbSettings->adsbServerConnectEnabled()->setRawValue(
false);
Q_APPLICATION_STATIC(ADSBVehicleManager, _adsbVehicleManager, SettingsManager::instance() ->adsbVehicleManagerSettings())
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
The ADSBTCPLink class handles the TCP connection to an ADS-B server and processes incoming ADS-B data...
bool init()
Attempts connection to a host.
void errorOccurred(const QString &errorMsg, bool stopped=false)
void adsbVehicleUpdate(const ADSB::VehicleInfo_t &vehicleInfo)
void adsbVehicleUpdate(const ADSB::VehicleInfo_t &vehicleInfo)
void mavlinkMessageReceived(const mavlink_message_t &message)
static ADSBVehicleManager * instance()
uint32_t icaoAddress() const
A Fact is used to hold a single value within the system.
void rawValueChanged(const QVariant &value)
QVariant rawValue() const
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
QObject * removeAt(int index)
int count() const override final
void clearAndDeleteContents() override final
Clears the list and calls deleteLater on each entry.
Provides access to all app settings.
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
AvailableInfoTypes availableFlags