mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-05 09:15:34 +08:00
refs #395, post merge and rebase adjustments plus further testing fixes:
* adjusted iterim position updates * removed deadlocks (thread safe values in airspace monitor) * resolved some merge issues * some smaller fixes in airspace monitor (style, finders)
This commit is contained in:
committed by
Mathew Sutcliffe
parent
6debd33b4f
commit
085edc82cb
@@ -32,6 +32,9 @@ namespace BlackCore
|
||||
m_network(network), m_vatsimBookingReader(bookings), m_vatsimDataFileReader(dataFile),
|
||||
m_analyzer(new CAirspaceAnalyzer(ownAircraftProvider, this, network, this))
|
||||
{
|
||||
this->setObjectName("CAirspaceMonitor");
|
||||
m_interimPositionUpdateTimer.setObjectName(this->objectName().append(":m_interimPositionUpdateTimer"));
|
||||
|
||||
this->connect(this->m_network, &INetwork::atcPositionUpdate, this, &CAirspaceMonitor::ps_atcPositionUpdate);
|
||||
this->connect(this->m_network, &INetwork::atisReplyReceived, this, &CAirspaceMonitor::ps_atisReceived);
|
||||
this->connect(this->m_network, &INetwork::atisVoiceRoomReplyReceived, this, &CAirspaceMonitor::ps_atisVoiceRoomReceived);
|
||||
@@ -49,8 +52,8 @@ namespace BlackCore
|
||||
this->connect(this->m_network, &INetwork::customFSinnPacketReceived, this, &CAirspaceMonitor::ps_customFSinnPacketReceived);
|
||||
this->connect(this->m_network, &INetwork::serverReplyReceived, this, &CAirspaceMonitor::ps_serverReplyReceived);
|
||||
this->connect(this->m_network, &INetwork::aircraftConfigPacketReceived, this, &CAirspaceMonitor::ps_aircraftConfigReceived);
|
||||
this->connect(&m_interimPositionUpdateTimer, &QTimer::timeout, this, &CAirspaceMonitor::ps_sendInterimPosition);
|
||||
|
||||
this->connect(&m_interimPositionUpdateTimer, &QTimer::timeout, this, &CAirspaceMonitor::ps_sendInterimPositions);
|
||||
|
||||
// AutoConnection: this should also avoid race conditions by updating the bookings
|
||||
this->connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CAirspaceMonitor::ps_receivedBookings);
|
||||
this->connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CAirspaceMonitor::ps_receivedDataFile);
|
||||
@@ -228,10 +231,11 @@ namespace BlackCore
|
||||
CCallsignSet searchList(callsigns);
|
||||
|
||||
// myself, which is not in the lists below
|
||||
if (!ownAircraft().getCallsign().isEmpty() && searchList.contains(ownAircraft().getCallsign()))
|
||||
CSimulatedAircraft myAircraft(ownAircraft());
|
||||
if (!myAircraft.getCallsign().isEmpty() && searchList.contains(myAircraft.getCallsign()))
|
||||
{
|
||||
searchList.remove(ownAircraft().getCallsign());
|
||||
users.push_back(ownAircraft().getPilot());
|
||||
searchList.remove(myAircraft.getCallsign());
|
||||
users.push_back(myAircraft.getPilot());
|
||||
}
|
||||
|
||||
// do aircraft first, this will handle most callsigns
|
||||
@@ -247,7 +251,7 @@ namespace BlackCore
|
||||
}
|
||||
}
|
||||
|
||||
foreach(CAtcStation station, this->m_atcStationsOnline)
|
||||
for (const CAtcStation &station : this->m_atcStationsOnline)
|
||||
{
|
||||
if (searchList.isEmpty()) break;
|
||||
CCallsign callsign = station.getCallsign();
|
||||
@@ -260,8 +264,8 @@ namespace BlackCore
|
||||
}
|
||||
|
||||
// we might have unresolved callsigns
|
||||
// these are the ones not in range
|
||||
foreach(CCallsign callsign, searchList)
|
||||
// those are the ones not in range
|
||||
for (const CCallsign &callsign : searchList)
|
||||
{
|
||||
CUserList usersByCallsign = this->m_vatsimDataFileReader->getUsersForCallsign(callsign);
|
||||
if (usersByCallsign.isEmpty())
|
||||
@@ -281,11 +285,8 @@ namespace BlackCore
|
||||
CClientList CAirspaceMonitor::getOtherClientsForCallsigns(const CCallsignSet &callsigns) const
|
||||
{
|
||||
CClientList clients;
|
||||
if (callsigns.isEmpty()) return clients;
|
||||
for (const CCallsign &callsign : callsigns)
|
||||
{
|
||||
clients.push_back(this->m_otherClients.findBy(&CClient::getCallsign, callsign));
|
||||
}
|
||||
if (callsigns.isEmpty()) { return clients; }
|
||||
clients.push_back(this->m_otherClients.findByCallsigns(callsigns));
|
||||
return clients;
|
||||
}
|
||||
|
||||
@@ -325,18 +326,14 @@ namespace BlackCore
|
||||
{
|
||||
CAtcStation station;
|
||||
CAtcStationList stations = this->m_atcStationsOnline.findIfComUnitTunedIn25KHz(comSystem);
|
||||
if (!stations.isEmpty())
|
||||
{
|
||||
stations.sortBy(&CAtcStation::getDistanceToOwnAircraft);
|
||||
station = stations.front();
|
||||
}
|
||||
return station;
|
||||
if (stations.isEmpty()) { return station; }
|
||||
stations.sortByDistanceToOwnAircraft();
|
||||
return stations.front();
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::requestDataUpdates()
|
||||
{
|
||||
if (!this->m_network->isConnected()) return;
|
||||
|
||||
if (!this->m_network->isConnected()) { return; }
|
||||
for (const CAircraft &aircraft : this->getAircraftInRange())
|
||||
{
|
||||
const CCallsign cs(aircraft.getCallsign());
|
||||
@@ -428,7 +425,7 @@ namespace BlackCore
|
||||
// Client
|
||||
vm = CPropertyIndexVariantMap({CClient::IndexUser, CUser::IndexRealName}, realname);
|
||||
vm.addValue({ CClient::IndexVoiceCapabilities }, caps);
|
||||
if (!this->m_otherClients.contains(&CClient::getCallsign, callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
if (!this->m_otherClients.containsCallsign(callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm);
|
||||
}
|
||||
|
||||
@@ -444,7 +441,7 @@ namespace BlackCore
|
||||
CPropertyIndexVariantMap vm(CClient::IndexCapabilities, capabilities.toCVariant());
|
||||
CVoiceCapabilities caps = m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign);
|
||||
vm.addValue({CClient::IndexVoiceCapabilities}, caps);
|
||||
if (!this->m_otherClients.contains(&CClient::getCallsign, callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
if (!this->m_otherClients.containsCallsign(callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm);
|
||||
|
||||
// apply same to client in aircraft
|
||||
@@ -464,7 +461,7 @@ namespace BlackCore
|
||||
// Request of other client, I can get the other's model from that
|
||||
CPropertyIndexVariantMap vm({ CClient::IndexModel, CAircraftModel::IndexModelString }, model);
|
||||
vm.addValue({ CClient::IndexModel, CAircraftModel::IndexModelType }, static_cast<int>(CAircraftModel::TypeQueriedFromNetwork));
|
||||
if (!this->m_otherClients.contains(&CClient::getCallsign, callsign))
|
||||
if (!this->m_otherClients.containsCallsign(callsign))
|
||||
{
|
||||
// with custom packets it can happen,
|
||||
// the packet is received before any other packet
|
||||
@@ -482,7 +479,6 @@ namespace BlackCore
|
||||
// if update was successful we know we have that callsign, otherwise explicit check
|
||||
aircraftContainsCallsign = (u > 0) || this->m_aircraftInRange.containsCallsign(callsign);
|
||||
}
|
||||
this->sendFsipiCustomPacket(callsign); // response
|
||||
|
||||
// ICAO response from custom data
|
||||
if (!aircraftDesignator.isEmpty())
|
||||
@@ -504,7 +500,7 @@ namespace BlackCore
|
||||
void CAirspaceMonitor::ps_serverReplyReceived(const CCallsign &callsign, const QString &server)
|
||||
{
|
||||
if (!this->m_connected || callsign.isEmpty() || server.isEmpty()) { return; }
|
||||
if (!this->m_otherClients.contains(&CClient::getCallsign, callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
if (!this->m_otherClients.containsCallsign(callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
|
||||
CPropertyIndexVariantMap vm(CClient::IndexServer, server);
|
||||
this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm);
|
||||
}
|
||||
@@ -522,8 +518,8 @@ namespace BlackCore
|
||||
this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsignTower, vm);
|
||||
this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsignTower, vm);
|
||||
this->m_metarCache.insert(icaoCode, metar);
|
||||
if (this->m_atcStationsOnline.contains(&CAtcStation::getCallsign, callsignTower)) { emit this->changedAtcStationsOnline(); }
|
||||
if (this->m_atcStationsBooked.contains(&CAtcStation::getCallsign, callsignTower)) { emit this->changedAtcStationsBooked(); }
|
||||
if (this->m_atcStationsOnline.containsCallsign(callsignTower)) { emit this->changedAtcStationsOnline(); }
|
||||
if (this->m_atcStationsBooked.containsCallsign(callsignTower)) { emit this->changedAtcStationsBooked(); }
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_flightPlanReceived(const CCallsign &callsign, const CFlightPlan &flightPlan)
|
||||
@@ -540,16 +536,14 @@ namespace BlackCore
|
||||
|
||||
void CAirspaceMonitor::removeAllAircraft()
|
||||
{
|
||||
QWriteLocker l1(&m_lockParts);
|
||||
QWriteLocker l2(&m_lockSituations);
|
||||
QWriteLocker l3(&m_lockAircraft);
|
||||
|
||||
for (const CAircraft &aircraft : m_aircraftInRange)
|
||||
for (const CAircraft &aircraft : getAircraftInRange())
|
||||
{
|
||||
const CCallsign cs(aircraft.getCallsign());
|
||||
emit removedAircraft(cs);
|
||||
}
|
||||
|
||||
QWriteLocker l1(&m_lockParts);
|
||||
QWriteLocker l2(&m_lockSituations);
|
||||
m_situationsByCallsign.clear();
|
||||
m_partsByCallsign.clear();
|
||||
m_aircraftSupportingParts.clear();
|
||||
@@ -601,21 +595,18 @@ namespace BlackCore
|
||||
void CAirspaceMonitor::ps_receivedDataFile()
|
||||
{
|
||||
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
|
||||
for (auto i = this->m_otherClients.begin(); i != this->m_otherClients.end(); ++i)
|
||||
for (auto client = this->m_otherClients.begin(); client != this->m_otherClients.end(); ++client)
|
||||
{
|
||||
CClient client = (*i);
|
||||
if (client.hasSpecifiedVoiceCapabilities()) continue;
|
||||
CVoiceCapabilities vc = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(client.getCallsign());
|
||||
if (vc.isUnknown()) continue;
|
||||
client.setVoiceCapabilities(vc);
|
||||
(*i) = client;
|
||||
if (client->hasSpecifiedVoiceCapabilities()) { continue; } // we already have voice caps
|
||||
CVoiceCapabilities vc = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(client->getCallsign());
|
||||
if (vc.isUnknown()) { continue; }
|
||||
client->setVoiceCapabilities(vc);
|
||||
}
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_sendReadyForModelMatching(const CCallsign &callsign, int trial)
|
||||
{
|
||||
// some checks for special conditions, e.g. logout -> empty list, but still signals pending
|
||||
// lock block
|
||||
CSimulatedAircraft remoteAircraft;
|
||||
{
|
||||
QReadLocker l(&m_lockAircraft);
|
||||
@@ -704,7 +695,7 @@ namespace BlackCore
|
||||
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
|
||||
|
||||
this->m_otherClients.removeByCallsign(callsign);
|
||||
if (this->m_atcStationsOnline.contains(&CAtcStation::getCallsign, callsign))
|
||||
if (this->m_atcStationsOnline.containsCallsign(callsign))
|
||||
{
|
||||
CAtcStation removedStation = this->m_atcStationsOnline.findFirstByCallsign(callsign);
|
||||
this->m_atcStationsOnline.removeByCallsign(callsign);
|
||||
@@ -799,6 +790,7 @@ namespace BlackCore
|
||||
}
|
||||
// ICAO code received when aircraft is already removed or not yet ready
|
||||
// We add it to cache and use it when aircraft is created
|
||||
int c;
|
||||
{
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
if (!this->m_aircraftInRange.containsCallsign(callsign))
|
||||
@@ -808,18 +800,18 @@ namespace BlackCore
|
||||
}
|
||||
|
||||
// update
|
||||
int c = this->m_aircraftInRange.applyIfCallsign(callsign, vm);
|
||||
if (c > 0) { ps_sendReadyForModelMatching(callsign, 1); }
|
||||
c = this->m_aircraftInRange.applyIfCallsign(callsign, vm);
|
||||
}
|
||||
if (c > 0) { ps_sendReadyForModelMatching(callsign, 1); }
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_aircraftUpdateReceived(const CAircraftSituation &situation, const CTransponder &transponder)
|
||||
{
|
||||
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), "ps_aircraftUpdateReceived", "Called in different thread");
|
||||
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), Q_FUNC_INFO, "Called in different thread");
|
||||
if (!this->m_connected) { return; }
|
||||
|
||||
CCallsign callsign(situation.getCallsign());
|
||||
Q_ASSERT_X(!callsign.isEmpty(), "ps_aircraftUpdateReceived", "Empty callsign");
|
||||
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "Empty callsign");
|
||||
|
||||
// store situation history
|
||||
this->storeAircraftSituation(situation);
|
||||
@@ -852,7 +844,7 @@ namespace BlackCore
|
||||
this->m_aircraftInRange.push_back(aircraft);
|
||||
|
||||
// new client, there is a chance it has been already created by custom packet
|
||||
if (!this->m_otherClients.contains(&CClient::getCallsign, callsign))
|
||||
if (!this->m_otherClients.containsCallsign(callsign))
|
||||
{
|
||||
CClient c(callsign);
|
||||
this->m_otherClients.push_back(c); // initial, will be filled by data later
|
||||
@@ -905,38 +897,41 @@ namespace BlackCore
|
||||
|
||||
void CAirspaceMonitor::ps_aircraftInterimUpdateReceived(const CAircraftSituation &situation)
|
||||
{
|
||||
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), "ps_aircraftInterimUpdateReceived", "Called in different thread");
|
||||
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), Q_FUNC_INFO, "Called in different thread");
|
||||
if (!this->m_connected) { return; }
|
||||
|
||||
CCallsign callsign(situation.getCallsign());
|
||||
Q_ASSERT_X(!callsign.isEmpty(), "ps_aircraftInterimUpdateReceived", "Empty callsign");
|
||||
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "Empty callsign");
|
||||
|
||||
// todo: Check if the timestamp is copied here as well.
|
||||
CAircraftSituation sitationCopy(situation);
|
||||
|
||||
// Interim packets do not have groundspeed, hence set the last known value.
|
||||
// If there is no full position available yet, throw this interim position away.
|
||||
auto history = this->m_aircraftSituations.findByCallsign(callsign);
|
||||
if (history.empty()) return;
|
||||
sitationCopy.setGroundspeed(history.latestValue().getGroundSpeed());
|
||||
CAircraftSituation iterimSituation(situation);
|
||||
{
|
||||
QReadLocker l(&m_lockSituations);
|
||||
auto history = this->m_situationsByCallsign[callsign];
|
||||
if (history.empty()) { return; } // we need one full situation
|
||||
iterimSituation.setCurrentUtcTime();
|
||||
iterimSituation.setGroundspeed(history.latestValue().getGroundSpeed());
|
||||
}
|
||||
|
||||
// store situation history
|
||||
this->m_aircraftSituations.push_front(situation);
|
||||
this->m_aircraftSituations.removeOlderThanNowMinusOffset(AircraftSituationsRemovedOffsetMs);
|
||||
emit this->addedRemoteAircraftSituation(situation);
|
||||
this->storeAircraftSituation(iterimSituation);
|
||||
emit this->addedAircraftSituation(iterimSituation);
|
||||
|
||||
// update
|
||||
CLength distance = ownAircraft().calculateGreatCircleDistance(situation.getPosition());
|
||||
distance.switchUnit(CLengthUnit::NM());
|
||||
// update aircraft
|
||||
//! \todo skip aircraft updates for interim positions as for performance reasons
|
||||
CLength distance = ownAircraft().calculateGreatCircleDistance(iterimSituation.getPosition());
|
||||
distance.switchUnit(CLengthUnit::NM()); // lloks nicer
|
||||
CPropertyIndexVariantMap vm;
|
||||
vm.addValue(CAircraft::IndexSituation, situation);
|
||||
vm.addValue(CAircraft::IndexSituation, iterimSituation);
|
||||
vm.addValue(CAircraft::IndexDistanceToOwnAircraft, distance);
|
||||
|
||||
// here I expect always a changed value
|
||||
this->m_aircraftInRange.applyIfCallsign(callsign, vm);
|
||||
this->m_aircraftWatchdog.resetCallsign(callsign);
|
||||
|
||||
emit this->changedAircraftInRange();
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
this->m_aircraftInRange.applyIfCallsign(callsign, vm);
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_pilotDisconnected(const CCallsign &callsign)
|
||||
@@ -956,13 +951,14 @@ namespace BlackCore
|
||||
m_aircraftSupportingParts.remove(callsign);
|
||||
}
|
||||
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
bool contains = this->m_aircraftInRange.containsCallsign(callsign);
|
||||
if (contains)
|
||||
bool containsCallsign;
|
||||
{
|
||||
this->m_aircraftInRange.removeByCallsign(callsign);
|
||||
emit this->removedAircraft(callsign);
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
containsCallsign = this->m_aircraftInRange.containsCallsign(callsign);
|
||||
if (containsCallsign) { this->m_aircraftInRange.removeByCallsign(callsign); }
|
||||
}
|
||||
|
||||
if (containsCallsign) { emit this->removedAircraft(callsign); }
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_frequencyReceived(const CCallsign &callsign, const CFrequency &frequency)
|
||||
@@ -970,23 +966,23 @@ namespace BlackCore
|
||||
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
|
||||
|
||||
// update
|
||||
int changed;
|
||||
CPropertyIndexVariantMap vm({CAircraft::IndexCom1System, CComSystem::IndexActiveFrequency}, frequency.toCVariant());
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
int changed = this->m_aircraftInRange.applyIf(&CAircraft::getCallsign, callsign, vm, true);
|
||||
{
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
changed = this->m_aircraftInRange.applyIf(&CAircraft::getCallsign, callsign, vm, true);
|
||||
}
|
||||
if (changed > 0) { emit this->changedAircraftInRange(); }
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_aircraftConfigReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &jsonObject, bool isFull)
|
||||
void CAirspaceMonitor::ps_aircraftConfigReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &jsonObject, bool isFull)
|
||||
{
|
||||
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
|
||||
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
CSimulatedAircraftList list = this->m_aircraftInRange.findByCallsign(callsign);
|
||||
// Skip unknown callsigns
|
||||
if (list.isEmpty()) { return; }
|
||||
CSimulatedAircraft simAircraft(getAircraftForCallsign(callsign));
|
||||
|
||||
CSimulatedAircraft simAircraft = list.front();
|
||||
// If we are not yet synchronized, we throw away any incremental packet
|
||||
if (!simAircraft.hasValidCallsign()) { return; }
|
||||
if (!simAircraft.isPartsSynchronized() && !isFull) { return; }
|
||||
|
||||
CAircraftParts parts;
|
||||
@@ -1011,39 +1007,41 @@ namespace BlackCore
|
||||
emit this->addedAircraftParts(parts);
|
||||
|
||||
// here I expect always a changed value
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
this->m_aircraftInRange.setAircraftParts(callsign, parts);
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::ps_sendInterimPosition()
|
||||
void CAirspaceMonitor::ps_sendInterimPositions()
|
||||
{
|
||||
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
|
||||
if (!this->m_connected || !m_sendInterimPositions) { return; }
|
||||
CSimulatedAircraftList aircrafts = m_aircraftInRange.findBy(&CSimulatedAircraft::fastPositionUpdates, true);
|
||||
m_network->sendInterimPosition(aircrafts.getCallsigns());
|
||||
m_network->sendInterimPositions(aircrafts.getCallsigns());
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation)
|
||||
void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation)
|
||||
{
|
||||
QWriteLocker lock(&m_lockSituations);
|
||||
const CCallsign callsign(situation.getCallsign());
|
||||
Q_ASSERT_X(!callsign.isEmpty(), "storeAircraftSituation", "empty callsign");
|
||||
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign");
|
||||
if (callsign.isEmpty()) { return; }
|
||||
|
||||
// list from new to old
|
||||
QWriteLocker lock(&m_lockSituations);
|
||||
CAircraftSituationList &l = this->m_situationsByCallsign[callsign];
|
||||
l.push_frontMaxElements(situation, MaxSituationsPerCallsign);
|
||||
|
||||
// check sort order
|
||||
Q_ASSERT_X(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch(), "storeAircraftSituation", "wrong sort order");
|
||||
Q_ASSERT_X(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch(), Q_FUNC_INFO, "wrong sort order");
|
||||
}
|
||||
|
||||
void CAirspaceMonitor::storeAircraftParts(const CAircraftParts &parts)
|
||||
{
|
||||
QWriteLocker lock(&m_lockParts);
|
||||
const CCallsign callsign(parts.getCallsign());
|
||||
Q_ASSERT_X(!callsign.isEmpty(), "storeAircraftParts", "empty callsign");
|
||||
if (callsign.isEmpty()) { return; }
|
||||
|
||||
// list sorted from new to old
|
||||
QWriteLocker lock(&m_lockParts);
|
||||
CAircraftPartsList &l = this->m_partsByCallsign[callsign];
|
||||
l.push_frontMaxElements(parts, MaxPartsPerCallsign);
|
||||
|
||||
|
||||
@@ -159,9 +159,6 @@ namespace BlackCore
|
||||
static const qint64 AircraftPartsRemoveOffsetMs = 30 * 1000; //!< parts older than now - offset will be removed
|
||||
|
||||
signals:
|
||||
|
||||
//--- DBus / local signals
|
||||
|
||||
//! Online ATC stations were changed
|
||||
void changedAtcStationsOnline();
|
||||
|
||||
@@ -218,11 +215,6 @@ namespace BlackCore
|
||||
mutable QReadWriteLock m_lockParts; //!< lock for parts
|
||||
mutable QReadWriteLock m_lockAircraft; //!< lock aircraft
|
||||
|
||||
// TODO FIXME (MS) should be in INetwork
|
||||
void sendFsipiCustomPacket(const BlackMisc::Aviation::CCallsign &recipientCallsign) const;
|
||||
void sendFsipirCustomPacket(const BlackMisc::Aviation::CCallsign &recipientCallsign) const;
|
||||
QStringList createFsipiCustomPacketData() const;
|
||||
|
||||
//! Remove ATC online stations
|
||||
void removeAllOnlineAtcStations();
|
||||
|
||||
@@ -274,7 +266,7 @@ namespace BlackCore
|
||||
void ps_receivedDataFile();
|
||||
void ps_aircraftConfigReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &jsonObject, bool isFull);
|
||||
void ps_aircraftInterimUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation);
|
||||
void ps_sendInterimPosition();
|
||||
void ps_sendInterimPositions();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace BlackCore
|
||||
* Send interim position directly to a set of receivers.
|
||||
* \pre Network must be connected when calling this function.
|
||||
*/
|
||||
virtual void sendInterimPosition(const BlackMisc::Aviation::CCallsignSet &receiver) = 0;
|
||||
virtual void sendInterimPositions(const BlackMisc::Aviation::CCallsignSet &receiver) = 0;
|
||||
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -119,14 +119,15 @@ namespace BlackCore
|
||||
|
||||
if (isConnected())
|
||||
{
|
||||
CSimulatedAircraft myAircraft(ownAircraft());
|
||||
if (this->m_loginMode == LoginAsObserver)
|
||||
{
|
||||
// Observer
|
||||
VatAtcPosition pos;
|
||||
pos.facility = vatFacilityTypeUnknown;
|
||||
pos.visibleRange = 10; // NM
|
||||
pos.latitude = ownAircraft().latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = ownAircraft().longitude().value(CAngleUnit::deg());
|
||||
pos.latitude = myAircraft.latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = myAircraft.longitude().value(CAngleUnit::deg());
|
||||
pos.elevation = 0;
|
||||
pos.rating = vatAtcRatingObserver;
|
||||
pos.frequency = 199998;
|
||||
@@ -137,18 +138,18 @@ namespace BlackCore
|
||||
// Normal / Stealth mode
|
||||
VatPilotPosition pos;
|
||||
// TODO: we need to distinguish true and pressure altitude
|
||||
pos.altitudePressure = ownAircraft().getAltitude().value(CLengthUnit::ft());
|
||||
pos.altitudeTrue = ownAircraft().getAltitude().value(CLengthUnit::ft());
|
||||
pos.heading = ownAircraft().getHeading().value(CAngleUnit::deg());
|
||||
pos.pitch = ownAircraft().getPitch().value(CAngleUnit::deg());
|
||||
pos.bank = ownAircraft().getBank().value(CAngleUnit::deg());
|
||||
pos.latitude = ownAircraft().latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = ownAircraft().longitude().value(CAngleUnit::deg());
|
||||
pos.groundSpeed = ownAircraft().getGroundSpeed().value(CSpeedUnit::kts());
|
||||
pos.altitudePressure = myAircraft.getAltitude().value(CLengthUnit::ft());
|
||||
pos.altitudeTrue = myAircraft.getAltitude().value(CLengthUnit::ft());
|
||||
pos.heading = myAircraft.getHeading().value(CAngleUnit::deg());
|
||||
pos.pitch = myAircraft.getPitch().value(CAngleUnit::deg());
|
||||
pos.bank = myAircraft.getBank().value(CAngleUnit::deg());
|
||||
pos.latitude = myAircraft.latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = myAircraft.longitude().value(CAngleUnit::deg());
|
||||
pos.groundSpeed = myAircraft.getGroundSpeed().value(CSpeedUnit::kts());
|
||||
pos.rating = vatPilotRatingUnknown;
|
||||
pos.transponderCode = static_cast<qint16>(ownAircraft().getTransponderCode());
|
||||
pos.transponderCode = static_cast<qint16>(myAircraft.getTransponderCode());
|
||||
pos.transponderMode = vatTransponderModeStandby;
|
||||
switch (ownAircraft().getTransponderMode())
|
||||
switch (myAircraft.getTransponderMode())
|
||||
{
|
||||
case CTransponder::ModeC: pos.transponderMode = vatTransponderModeCharlie; break;
|
||||
case CTransponder::StateIdent: pos.transponderMode = vatTransponderModeIdent; break;
|
||||
@@ -422,20 +423,21 @@ namespace BlackCore
|
||||
Vat_SendClientQuery(m_net.data(), vatClientQueryInfo, toFSD(callsign));
|
||||
}
|
||||
|
||||
void CNetworkVatlib::sendInterimPosition(const CCallsignSet &receivers)
|
||||
void CNetworkVatlib::sendInterimPositions(const CCallsignSet &receivers)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
if (receivers.isEmpty()) { return; }
|
||||
CSimulatedAircraft myAircraft(ownAircraft());
|
||||
if (this->m_loginMode == LoginNormal)
|
||||
{
|
||||
VatInterimPilotPosition pos;
|
||||
// TODO: we need to distinguish true and pressure altitude
|
||||
pos.altitudeTrue = ownAircraft().getAltitude().value(CLengthUnit::ft());
|
||||
pos.heading = ownAircraft().getHeading().value(CAngleUnit::deg());
|
||||
pos.pitch = ownAircraft().getPitch().value(CAngleUnit::deg());
|
||||
pos.bank = ownAircraft().getBank().value(CAngleUnit::deg());
|
||||
pos.latitude = ownAircraft().latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = ownAircraft().longitude().value(CAngleUnit::deg());
|
||||
pos.altitudeTrue = myAircraft.getAltitude().value(CLengthUnit::ft());
|
||||
pos.heading = myAircraft.getHeading().value(CAngleUnit::deg());
|
||||
pos.pitch = myAircraft.getPitch().value(CAngleUnit::deg());
|
||||
pos.bank = myAircraft.getBank().value(CAngleUnit::deg());
|
||||
pos.latitude = myAircraft.latitude().value(CAngleUnit::deg());
|
||||
pos.longitude = myAircraft.longitude().value(CAngleUnit::deg());
|
||||
|
||||
for (const auto &receiver : receivers)
|
||||
{
|
||||
@@ -615,7 +617,8 @@ namespace BlackCore
|
||||
if (modelString.isEmpty()) { modelString = defaultModelString(); }
|
||||
|
||||
QStringList data { { "0" }, icao.getAirlineDesignator(), icao.getAircraftDesignator(),
|
||||
{ "" }, { "" }, { "" }, { "" }, icao.getAircraftCombinedType(), modelString };
|
||||
{ "" }, { "" }, { "" }, { "" }, icao.getAircraftCombinedType(), modelString
|
||||
};
|
||||
sendCustomPacket(callsign, "FSIPIR", data);
|
||||
}
|
||||
|
||||
@@ -627,7 +630,8 @@ namespace BlackCore
|
||||
if (modelString.isEmpty()) { modelString = defaultModelString(); }
|
||||
|
||||
QStringList data { { "0" }, icao.getAirlineDesignator(), icao.getAircraftDesignator(),
|
||||
{ "" }, { "" }, { "" }, { "" }, icao.getAircraftCombinedType(), modelString };
|
||||
{ "" }, { "" }, { "" }, { "" }, icao.getAircraftCombinedType(), modelString
|
||||
};
|
||||
sendCustomPacket(callsign, "FSIPI", data);
|
||||
}
|
||||
|
||||
@@ -877,11 +881,11 @@ namespace BlackCore
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case vatInfoQueryTypeFreq: emit cbvar_cast(cbvar)->frequencyReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break;
|
||||
case vatInfoQueryTypeServer: emit cbvar_cast(cbvar)->serverReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case vatInfoQueryTypeAtc: emit cbvar_cast(cbvar)->atcReplyReceived(CCallsign(cbvar_cast(cbvar)->fromFSD(data2), CCallsign::Atc), *data == 'Y'); break;
|
||||
case vatInfoQueryTypeName: emit cbvar_cast(cbvar)->realNameReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case vatInfoQueryTypeIP: emit cbvar_cast(cbvar)->ipReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case vatClientQueryFreq: emit cbvar_cast(cbvar)->frequencyReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break;
|
||||
case vatClientQueryServer: emit cbvar_cast(cbvar)->serverReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case vatClientQueryAtc: emit cbvar_cast(cbvar)->atcReplyReceived(CCallsign(cbvar_cast(cbvar)->fromFSD(data2), CCallsign::Atc), *data == 'Y'); break;
|
||||
case vatClientQueryName: emit cbvar_cast(cbvar)->realNameReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case vatClientQueryIP: emit cbvar_cast(cbvar)->ipReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace BlackCore
|
||||
virtual void sendIcaoCodesQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
virtual void sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
virtual void sendUserInfoQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
virtual void sendInterimPosition(const BlackMisc::Aviation::CCallsignSet &receiver) override;
|
||||
virtual void sendInterimPositions(const BlackMisc::Aviation::CCallsignSet &receiver) override;
|
||||
//! @}
|
||||
|
||||
//! \name Weather slots
|
||||
|
||||
Reference in New Issue
Block a user