diff --git a/samples/cli_client/client.cpp b/samples/cli_client/client.cpp index 27e5680b1..d4a427ebf 100644 --- a/samples/cli_client/client.cpp +++ b/samples/cli_client/client.cpp @@ -43,10 +43,10 @@ Client::Client(BlackMisc::IContext &ctx) connect(this, &Client::sendNameQuery, m_net, &INetwork::sendNameQuery); connect(this, &Client::sendCapabilitiesQuery, m_net, &INetwork::sendCapabilitiesQuery); connect(this, &Client::requestPlaneInfo, m_net, &INetwork::requestAircraftInfo); + connect(this, &Client::setOwnAircraft, m_net, &INetwork::setOwnAircraft); connect(this, &Client::setOwnAircraftPosition, m_net, &INetwork::setOwnAircraftPosition); - connect(this, &Client::setOwnAircraftTransponder, m_net, &INetwork::setOwnAircraftTransponder); - connect(this, &Client::setOwnAircraftFrequency, m_net, &INetwork::setOwnAircraftFrequency); - connect(this, &Client::setOwnAircraftIcao, m_net, &INetwork::setOwnAircraftIcao); + connect(this, &Client::setOwnAircraftSituation, m_net, &INetwork::setOwnAircraftSituation); + connect(this, &Client::setOwnAircraftAvionics, m_net, &INetwork::setOwnAircraftAvionics); connect(this, &Client::ping, m_net, &INetwork::ping); connect(this, &Client::requestMetar, m_net, &INetwork::requestMetar); connect(this, &Client::requestWeatherData, m_net, &INetwork::requestWeatherData); @@ -70,10 +70,10 @@ Client::Client(BlackMisc::IContext &ctx) m_commands["name"] = std::bind(&Client::sendNameQueryCmd, this, _1); m_commands["caps"] = std::bind(&Client::sendCapabilitiesQueryCmd, this, _1); m_commands["aircraftinfo"] = std::bind(&Client::requestAircraftInfoCmd, this, _1); + m_commands["setaircraft"] = std::bind(&Client::setOwnAircraftCmd, this, _1); m_commands["setposition"] = std::bind(&Client::setOwnAircraftPositionCmd, this, _1); - m_commands["setsquawk"] = std::bind(&Client::setOwnAircraftTransponderCmd, this, _1); - m_commands["setfreq"] = std::bind(&Client::setOwnAircraftFrequencyCmd, this, _1); - m_commands["seticao"] = std::bind(&Client::setOwnAircraftIcaoCmd, this, _1); + m_commands["setsituation"] = std::bind(&Client::setOwnAircraftSituationCmd, this, _1); + m_commands["setavionics"] = std::bind(&Client::setOwnAircraftAvionicsCmd, this, _1); m_commands["ping"] = std::bind(&Client::pingCmd, this, _1); m_commands["metar"] = std::bind(&Client::requestMetarCmd, this, _1); m_commands["weather"] = std::bind(&Client::requestWeatherDataCmd, this, _1); @@ -230,54 +230,72 @@ void Client::requestAircraftInfoCmd(QTextStream &args) emit requestPlaneInfo(callsign); } -void Client::setOwnAircraftFrequencyCmd(QTextStream &args) -{ - QString callsign; - double num; - args >> callsign >> num; - BlackMisc::PhysicalQuantities::CFrequency freq(num, BlackMisc::PhysicalQuantities::CFrequencyUnit::kHz()); - emit setOwnAircraftFrequency(freq); -} - -void Client::setOwnAircraftIcaoCmd(QTextStream &args) +void Client::setOwnAircraftCmd(QTextStream &args) { QString callsign; QString acTypeICAO; QString airlineICAO; QString livery; - args >> callsign >> acTypeICAO >> airlineICAO >> livery; - BlackMisc::Aviation::CAircraftIcao icao(acTypeICAO, "L2J", airlineICAO, livery, ""); - emit setOwnAircraftIcao(icao); + double lat; + double lon; + double alt; + double hdg; + double pitch; + double bank; + double gs; + args >> callsign >> acTypeICAO >> airlineICAO >> livery >> lat >> lon >> alt >> hdg >> pitch >> bank >> gs; + emit setOwnAircraft(BlackMisc::Aviation::CAircraft(callsign, BlackMisc::Network::CUser(), BlackMisc::Aviation::CAircraftSituation( + BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0), + BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()), + BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts()) + ))); } void Client::setOwnAircraftPositionCmd(QTextStream &args) { - QString lat; - QString lon; - QString alt; - QString speed; - QString hdg; - QString pitch; - QString bank; - args >> lat >> lon >> alt >> speed >> hdg >> pitch >> bank; - BlackMisc::Aviation::CAircraftSituation position(BlackMisc::Geo::CCoordinateGeodetic(lat.toDouble(), lon.toDouble(), 0), - BlackMisc::Aviation::CAltitude(alt.toDouble(), BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()), - BlackMisc::Aviation::CHeading(hdg.toDouble(), BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), - BlackMisc::PhysicalQuantities::CAngle(pitch.toDouble(), BlackMisc::PhysicalQuantities::CAngleUnit::deg()), - BlackMisc::PhysicalQuantities::CAngle(bank.toDouble(), BlackMisc::PhysicalQuantities::CAngleUnit::deg()), - BlackMisc::PhysicalQuantities::CSpeed(speed.toDouble(), BlackMisc::PhysicalQuantities::CSpeedUnit::kts())); - emit setOwnAircraftPosition(position); + double lat; + double lon; + double alt; + args >> lat >> lon >> alt; + emit setOwnAircraftPosition(BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0), + BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft())); } -void Client::setOwnAircraftTransponderCmd(QTextStream &args) +void Client::setOwnAircraftSituationCmd(QTextStream &args) { - QString code; - QString mode; - args >> code >> mode; - BlackMisc::Aviation::CTransponder xpdr("transponder", code.toInt(), BlackMisc::Aviation::CTransponder::StateStandby); - if (mode == "c") { xpdr.setTransponderCode(BlackMisc::Aviation::CTransponder::ModeC); } - else if (mode == "i") { xpdr.setTransponderCode(BlackMisc::Aviation::CTransponder::StateIdent); } - emit setOwnAircraftTransponder(xpdr); + double lat; + double lon; + double alt; + double hdg; + double pitch; + double bank; + double gs; + args >> lat >> lon >> alt >> hdg >> pitch >> bank >> gs; + emit setOwnAircraftSituation(BlackMisc::Aviation::CAircraftSituation( + BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0), + BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()), + BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()), + BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts()) + )); +} + +void Client::setOwnAircraftAvionicsCmd(QTextStream &args) +{ + double com1; + double com2; + int xpdrCode; + QString xpdrMode; + args >> com1 >> com2 >> xpdrCode >> xpdrMode; + emit setOwnAircraftAvionics( + BlackMisc::Aviation::CComSystem("COM1", BlackMisc::PhysicalQuantities::CFrequency(com1, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())), + BlackMisc::Aviation::CComSystem("COM2", BlackMisc::PhysicalQuantities::CFrequency(com2, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())), + BlackMisc::Aviation::CTransponder("Transponder", xpdrCode, xpdrMode) + ); } void Client::pingCmd(QTextStream &args) @@ -316,13 +334,21 @@ void Client::atcDisconnected(const BlackMisc::Aviation::CCallsign &callsign) std::cout << "ATC_DISCONNECTED " << callsign << std::endl; } -void Client::connectionStatusChanged(BlackCore::INetwork::ConnectionStatus status) +void Client::connectionStatusChanged(BlackCore::INetwork::ConnectionStatus oldStatus, BlackCore::INetwork::ConnectionStatus newStatus) { - switch (status) + switch (newStatus) { - case BlackCore::INetwork::Disconnected: std::cout << "CONN_STATUS_DISCONNECTED" << std::endl; break; - case BlackCore::INetwork::Connecting: std::cout << "CONN_STATUS_CONNECTING" << std::endl; break; - case BlackCore::INetwork::Connected: std::cout << "CONN_STATUS_CONNECTED" << std::endl; break; + case BlackCore::INetwork::Disconnected: std::cout << "CONN_STATUS_DISCONNECTED"; break; + case BlackCore::INetwork::DisconnectedError: std::cout << "CONN_STATUS_DISCONNECTED_ERROR"; break; + case BlackCore::INetwork::Connecting: std::cout << "CONN_STATUS_CONNECTING"; break; + case BlackCore::INetwork::Connected: std::cout << "CONN_STATUS_CONNECTED"; break; + } + switch (oldStatus) + { + case BlackCore::INetwork::Disconnected: std::cout << " (was CONN_STATUS_DISCONNECTED)\n"; break; + case BlackCore::INetwork::DisconnectedError: std::cout << " (was CONN_STATUS_DISCONNECTED_ERROR)\n"; break; + case BlackCore::INetwork::Connecting: std::cout << " (was CONN_STATUS_CONNECTING)\n"; break; + case BlackCore::INetwork::Connected: std::cout << " (was CONN_STATUS_CONNECTED)\n"; break; } } diff --git a/samples/cli_client/client.h b/samples/cli_client/client.h index 2f822bb26..dd2a58208 100644 --- a/samples/cli_client/client.h +++ b/samples/cli_client/client.h @@ -45,10 +45,10 @@ private: //commands void sendNameQueryCmd(QTextStream &args); void sendCapabilitiesQueryCmd(QTextStream &args); void requestAircraftInfoCmd(QTextStream &args); + void setOwnAircraftCmd(QTextStream &args); void setOwnAircraftPositionCmd(QTextStream &args); - void setOwnAircraftTransponderCmd(QTextStream &args); - void setOwnAircraftFrequencyCmd(QTextStream &args); - void setOwnAircraftIcaoCmd(QTextStream &args); + void setOwnAircraftSituationCmd(QTextStream &args); + void setOwnAircraftAvionicsCmd(QTextStream &args); void pingCmd(QTextStream &args); void requestMetarCmd(QTextStream &args); void requestWeatherDataCmd(QTextStream &args); @@ -69,10 +69,11 @@ signals: //to send to INetwork void sendNameQuery(const BlackMisc::Aviation::CCallsign &callsign); void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign); void requestPlaneInfo(const BlackMisc::Aviation::CCallsign &callsign); - void setOwnAircraftPosition(const BlackMisc::Aviation::CAircraftSituation &position); - void setOwnAircraftTransponder(const BlackMisc::Aviation::CTransponder &xpdr); - void setOwnAircraftFrequency(const BlackMisc::PhysicalQuantities::CFrequency &freq); - void setOwnAircraftIcao(const BlackMisc::Aviation::CAircraftIcao &icao); + void setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft); + void setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude); + void setOwnAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + void setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2, + const BlackMisc::Aviation::CTransponder &xpdr); void ping(const BlackMisc::Aviation::CCallsign &callsign); void requestMetar(const QString &airportICAO); void requestWeatherData(const QString &airportICAO); @@ -81,7 +82,7 @@ public slots: //to receive from INetwork void atcPositionUpdate(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq, const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range); void atcDisconnected(const BlackMisc::Aviation::CCallsign &callsign); - void connectionStatusChanged(BlackCore::INetwork::ConnectionStatus status); + void connectionStatusChanged(BlackCore::INetwork::ConnectionStatus oldStatus, BlackCore::INetwork::ConnectionStatus newStatus); void ipQueryReplyReceived(const QString &ip); void freqQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq); void serverQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &hostname); diff --git a/src/blackcore/context_network.cpp b/src/blackcore/context_network.cpp index 114393ad4..613708a2f 100644 --- a/src/blackcore/context_network.cpp +++ b/src/blackcore/context_network.cpp @@ -38,24 +38,30 @@ namespace BlackCore this->connect(this->m_atcBookingTimer, SIGNAL(timeout()), this, SLOT(readAtcBookingsFromSource())); this->m_atcBookingTimer->start(15 * 1000); + + // 4. connect signals and slots bool connect; connect = this->connect(this->m_network, SIGNAL(connectionStatusChanged(INetwork::ConnectionStatus, INetwork::ConnectionStatus)), this, SLOT(psFsdConnectionStatusChanged(INetwork::ConnectionStatus, INetwork::ConnectionStatus))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect connectionStatusChanged"); - connect = this->connect(this->m_network, SIGNAL(terminate()), - this, SLOT(psFsdConnectionTerminated())); - Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect terminate"); - connect = this->connect(this->m_network, SIGNAL(atcPositionUpdate(BlackMisc::Aviation::CCallsign, BlackMisc::PhysicalQuantities::CFrequency, BlackMisc::Geo::CCoordinateGeodetic, BlackMisc::PhysicalQuantities::CLength)), this, SLOT(psFsdAtcPositionUpdate(BlackMisc::Aviation::CCallsign, BlackMisc::PhysicalQuantities::CFrequency, BlackMisc::Geo::CCoordinateGeodetic, BlackMisc::PhysicalQuantities::CLength))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect atcPositionUpdate"); - connect = this->connect(this->m_network, SIGNAL(atisQueryReplyReceived(BlackMisc::Aviation::CCallsign, Cvatlib_Network::atisLineType, QString)), - this, SLOT(psFsdAtisQueryReceived(BlackMisc::Aviation::CCallsign, Cvatlib_Network::atisLineType, QString))); + connect = this->connect(this->m_network, SIGNAL(atisQueryReplyReceived(BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CInformationMessage)), + this, SLOT(psFsdAtisQueryReceived(BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CInformationMessage))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect atis"); + connect = this->connect(this->m_network, SIGNAL(atisQueryVoiceRoomReplyReceived(BlackMisc::Aviation::CCallsign, QString)), + this, SLOT(psFsdAtisVoiceRoomQueryReceived(BlackMisc::Aviation::CCallsign, QString))); + Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect atis voice room"); + + connect = this->connect(this->m_network, SIGNAL(atisQueryLogoffTimeReplyReceived(BlackMisc::Aviation::CCallsign, QString)), + this, SLOT(psFsdAtisLogoffTimeQueryReceived(BlackMisc::Aviation::CCallsign, QString))); + Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect atis logoff time"); + connect = this->connect(this->m_network, SIGNAL(metarReceived(QString)), this, SLOT(psFsdMetarReceived(QString))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect metar"); @@ -64,10 +70,6 @@ namespace BlackCore this, SLOT(psFsdNameQueryReplyReceived(BlackMisc::Aviation::CCallsign, QString))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect name reply"); - connect = this->connect(this->m_network, SIGNAL(exception(QString, bool)), - this, SLOT(psVatlibExceptionMessage(QString, bool))); - Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect exception"); - connect = this->connect(this->m_network, SIGNAL(aircraftInfoReceived(BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftIcao)), this, SLOT(psFsdAircraftInfoReceived(BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftIcao))); Q_ASSERT_X(connect, "CContextNetwork", "Cannot connect aircraft info"); @@ -143,7 +145,7 @@ namespace BlackCore { msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityWarning, "Invalid user credentials")); } - else if (!this->m_network->isDisconnected()) + else if (this->m_network->isConnected()) { msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityWarning, "Already connected")); } @@ -167,11 +169,7 @@ namespace BlackCore { // this->log(Q_FUNC_INFO); CStatusMessageList msgs; - if (this->m_network->isDisconnected()) - { - msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityWarning, "Already disconnected")); - } - else + if (this->m_network->isConnected()) { this->m_network->terminateConnection(); this->m_aircraftsInRange.clear(); @@ -180,6 +178,10 @@ namespace BlackCore this->m_metarCache.clear(); msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityInfo, "Connection terminating")); } + else + { + msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityWarning, "Already disconnected")); + } return msgs; } @@ -188,7 +190,7 @@ namespace BlackCore */ bool CContextNetwork::isConnected() const { - return !this->m_network->isDisconnected(); + return this->m_network->isConnected(); } /* @@ -198,13 +200,13 @@ namespace BlackCore { // this->log(Q_FUNC_INFO, aircraft.toQString()); CStatusMessageList msgs; - if (this->m_network->isDisconnected()) + if (this->m_network->isConnected()) { - this->m_ownAircraft = aircraft; + msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityError, "Cannot set plane info, network already connected")); } else { - msgs.push_back(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityError, "Cannot set plane info, network already connected")); + this->m_ownAircraft = aircraft; } return msgs; } @@ -216,7 +218,7 @@ namespace BlackCore { this->m_ownAircraft.setPosition(position); this->m_ownAircraft.setAltitude(altitude); - this->m_network->updateOwnPosition(position, altitude); + this->m_network->setOwnAircraftPosition(position, altitude); } /* @@ -226,7 +228,7 @@ namespace BlackCore { // TODO: Do I really need own member? this->m_ownAircraft.setSituation(situation); - this->m_network->updateOwnSituation(situation); + this->m_network->setOwnAircraftSituation(situation); } /* @@ -252,7 +254,7 @@ namespace BlackCore } if (!changed) return; - this->m_network->updateOwnCockpit(com1, com2, transponder); + this->m_network->setOwnAircraftAvionics(com1, com2, transponder); } /* @@ -273,15 +275,6 @@ namespace BlackCore this->m_network->sendTextMessages(textMessages); } - /* - * Connection terminated - */ - void CContextNetwork::psFsdConnectionTerminated() - { - emit this->statusMessage(CStatusMessage(CStatusMessage::TypeTrafficNetwork, CStatusMessage::SeverityInfo, "connection terminated")); - emit this->connectionTerminated(); - } - /* * Connection status changed */ @@ -321,13 +314,4 @@ namespace BlackCore this->m_aircraftsInRange.applyIf(&CAircraft::getCallsign, callsign, vm); } - /* - * Exception to status message - */ - void CContextNetwork::psVatlibExceptionMessage(const QString &message, bool fatal) - { - CStatusMessage msg(CStatusMessage::TypeTrafficNetwork, fatal ? CStatusMessage::SeverityError : CStatusMessage::SeverityWarning, message); - emit this->statusMessage(msg); - } - } // namespace diff --git a/src/blackcore/context_network.h b/src/blackcore/context_network.h index 936e150cc..5846d6b84 100644 --- a/src/blackcore/context_network.h +++ b/src/blackcore/context_network.h @@ -185,7 +185,6 @@ namespace BlackCore BlackCore::INetwork *m_network; BlackMisc::Aviation::CAircraft m_ownAircraft; QMap m_metarCache /*!< Keep METARs for a while */; - QMap m_atisMessageBuilder; /*!< ATIS consists of several parts, complete ATIS needs to be concatenated */ // for reading XML QNetworkAccessManager *m_networkManager; @@ -228,11 +227,6 @@ namespace BlackCore void initOwnAircraft(); private slots: - /*! - * \brief Terminated connection - */ - void psFsdConnectionTerminated(); - /*! * \brief Connection status changed * \param from @@ -256,12 +250,25 @@ namespace BlackCore void psFsdAtcControllerDisconnected(const BlackMisc::Aviation::CCallsign &callsign); /*! - * \brief ATIS received (also relevant to get voice server) + * \brief ATIS received * \param callsign - * \param lineType * \param atisMessage */ - void psFsdAtisQueryReceived(const BlackMisc::Aviation::CCallsign &callsign, Cvatlib_Network::atisLineType lineType, const QString &atisMessage); + void psFsdAtisQueryReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atisMessage); + + /*! + * \brief ATIS received (voice room part) + * \param callsign + * \param url + */ + void psFsdAtisVoiceRoomQueryReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &url); + + /*! + * \brief ATIS received (logoff time part) + * \param callsign + * \param zuluTime + */ + void psFsdAtisLogoffTimeQueryReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime); /*! * \brief METAR received @@ -318,15 +325,8 @@ namespace BlackCore * TODO: encapsulate reading from WWW in some class */ void psAtcBookingsRead(QNetworkReply *nwReply); - - /*! - * \brief Exception message - * \param message - * \param fatal - */ - void psVatlibExceptionMessage(const QString &message, bool fatal); - }; + } #endif // guard diff --git a/src/blackcore/context_network_atc.cpp b/src/blackcore/context_network_atc.cpp index de27f0426..970dd3d20 100644 --- a/src/blackcore/context_network_atc.cpp +++ b/src/blackcore/context_network_atc.cpp @@ -119,7 +119,6 @@ namespace BlackCore station.setPosition(position); station.setOnline(true); station.calculcateDistanceToPlane(this->m_ownAircraft.getPosition()); - this->m_atisMessageBuilder[callsign.asString()] = ""; // reset ATIS builder this->m_atcStationsOnline.push_back(station); emit this->changedAtcStationsOnline(); emit this->m_network->sendAtisQuery(callsign); // request ATIS @@ -152,75 +151,45 @@ namespace BlackCore /* * ATIS received */ - void CContextNetwork::psFsdAtisQueryReceived(const CCallsign &callsign, Cvatlib_Network::atisLineType lineType, const QString &atisMessage) + void CContextNetwork::psFsdAtisQueryReceived(const CCallsign &callsign, const CInformationMessage &atisMessage) { // this->log(Q_FUNC_INFO, callsign.toQString(), atisMessage); - // The ATIS consists of several lines, so the complete - // message needs to be build up before it can be set - // :V -> voice room address. - // :T Controller atis message - // :E Zulu logoff time - // :Z atis line count including this one + CValueMap vm(CAtcStation::IndexAtisMessage, atisMessage.toQVariant()); + this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); + this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); + } - QString currentAtisMessage = this->m_atisMessageBuilder.contains(callsign.asString()) ? - this->m_atisMessageBuilder[callsign.asString()] : ""; - switch (lineType) + /* + * ATIS (voice room part) received + */ + void CContextNetwork::psFsdAtisVoiceRoomQueryReceived(const CCallsign &callsign, const QString &url) + { + QString trimmedUrl = url.trimmed(); + CValueMap vm(CAtcStation::IndexVoiceRoomUrl, trimmedUrl); + this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); + this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); + } + + /* + * ATIS (logoff time part) received + */ + void CContextNetwork::psFsdAtisLogoffTimeQueryReceived(const CCallsign &callsign, const QString &zuluTime) + { + if (zuluTime.length() == 4) { - case Cvatlib_Network::atisLineType_LineCount: - { - // line count denotes end of ATIS - CValueMap vm(CAtcStation::IndexAtisMessage, currentAtisMessage); - this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); - this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); - this->m_atisMessageBuilder.remove(callsign.asString()); - return; // ignore, nothing to do - } - case Cvatlib_Network::atisLineType_VoiceRoom: - { - QString voiceRoomUrl = atisMessage.trimmed(); - CValueMap vm(CAtcStation::IndexVoiceRoomUrl, voiceRoomUrl); - this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); - this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); - break; // voice room set, but also add to message - } - case Cvatlib_Network::atisLineType_ZuluLogoff: - { - if (atisMessage.length() == 4) - { - // Logic to set logoff time - bool ok; - int h = atisMessage.left(2).toInt(&ok); - if (!ok) break; - int m = atisMessage.right(2).toInt(&ok); - if (!ok) break; - QDateTime zuluLogoff = QDateTime::currentDateTimeUtc(); - zuluLogoff.setTime(QTime(h, m)); - CValueMap vm(CAtcStation::IndexBookedUntil, zuluLogoff); - this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); - this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); - } - break; // ZULU time set, but also add to message - } - case Cvatlib_Network::atisLineType_TextMessage: - break; - default: - break; + // Logic to set logoff time + bool ok; + int h = zuluTime.left(2).toInt(&ok); + if (!ok) return; + int m = zuluTime.right(2).toInt(&ok); + if (!ok) return; + QDateTime logoffDateTime = QDateTime::currentDateTimeUtc(); + logoffDateTime.setTime(QTime(h, m)); + CValueMap vm(CAtcStation::IndexBookedUntil, logoffDateTime); + this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm); + this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); } - - const QString fixedAtisMessage = atisMessage.trimmed(); - if (fixedAtisMessage.isEmpty()) return; - - // detect the stupid z1, z2, z3 placeholders - // TODO: Anything better as this stupid code here? - const QString atisTest = fixedAtisMessage.toLower().remove(QRegExp("[\\n\\t\\r]")); - if (atisTest == "z") return; - if (atisTest.startsWith("z") && atisTest.length() == 2) return; // z1, z2, .. - if (atisTest.length() == 1) return; // sometimes just z - - if (!currentAtisMessage.isEmpty()) currentAtisMessage.append("\n"); - currentAtisMessage.append(fixedAtisMessage); - this->m_atisMessageBuilder[callsign.asString()] = currentAtisMessage; } /* diff --git a/src/blackcore/network.h b/src/blackcore/network.h index 263d36bc1..bf360a765 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace BlackCore { @@ -58,10 +59,20 @@ namespace BlackCore enum ConnectionStatus { Disconnected = 0, + DisconnectedError, Connecting, Connected }; + QString connectionStatusToString(ConnectionStatus status) const + { + int index = metaObject()->indexOfEnumerator("ConnectionStatus"); + QMetaEnum metaEnum = metaObject()->enumerator(index); + return metaEnum.valueToKey(status); + } + + virtual bool isConnected() const = 0; + public slots: // Network virtual void setServer(const BlackMisc::Network::CServer &server) = 0; @@ -86,10 +97,11 @@ namespace BlackCore virtual void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0; virtual void requestAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign) = 0; virtual void sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0; - virtual void setOwnAircraftPosition(const BlackMisc::Aviation::CAircraftSituation &aircraft) = 0; - virtual void setOwnAircraftTransponder(const BlackMisc::Aviation::CTransponder &xpdr) = 0; - virtual void setOwnAircraftFrequency(const BlackMisc::PhysicalQuantities::CFrequency &freq) = 0; - virtual void setOwnAircraftIcao(const BlackMisc::Aviation::CAircraftIcao &icao) = 0; + virtual void setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft) = 0; + virtual void setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude) = 0; + virtual void setOwnAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) = 0; + virtual void setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2, + const BlackMisc::Aviation::CTransponder &xpdr) = 0; // Weather / flight plan virtual void requestMetar(const QString &airportICAO) = 0; @@ -103,6 +115,8 @@ namespace BlackCore void atcDisconnected(const BlackMisc::Aviation::CCallsign &callsign); void atcQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, bool isATC); void atisQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atis); + void atisQueryVoiceRoomReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &url); + void atisQueryLogoffTimeReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime); void metarReceived(const QString &data); // Aircraft @@ -114,8 +128,9 @@ namespace BlackCore void frequencyQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq); // Connection / Network in general + void statusMessage(const BlackMisc::CStatusMessage &message); void kicked(const QString &msg); - void connectionStatusChanged(ConnectionStatus status); + void connectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus); void pong(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CTime &elapsedTime); void capabilitiesQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, quint32 flags); void ipQueryReplyReceived(const QString &ip); diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 48c001264..60d707945 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -28,10 +28,11 @@ namespace BlackCore void exceptionDispatcher(const char* caller); - CNetworkVatlib::CNetworkVatlib(QObject *parent) + CNetworkVatlib::CNetworkVatlib(CNetworkVatlib::LoginMode loginMode, QObject *parent) : INetwork(parent), m_net(Cvatlib_Network::Create()), m_status(Cvatlib_Network::connStatus_Idle), + m_loginMode(loginMode), m_fsdTextCodec(QTextCodec::codecForName("latin1")) { try @@ -48,6 +49,11 @@ namespace BlackCore capabilities += "=1:"; capabilities += m_net->capability_ModelDesc; capabilities += "=1"; + if (loginMode == LoginStealth) + { + capabilities += "STEALTH"; // TODO m_net->capability_Stealth + capabilities += "=1"; + } m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, toFSD(capabilities)); @@ -116,24 +122,40 @@ namespace BlackCore { if (m_net->IsValid() && m_net->IsSessionExists()) { - Cvatlib_Network::PilotPosUpdate pos; - pos.altAdj = 0; // TODO - pos.altTrue = m_ownAircraft.getAltitude().value(CLengthUnit::ft()); - pos.bank = m_ownAircraft.getBank().value(CAngleUnit::deg()); - pos.groundSpeed = m_ownAircraft.getGroundSpeed().value(CSpeedUnit::kts()); - pos.heading = m_ownAircraft.getHeading().value(CAngleUnit::deg()); - pos.lat = m_ownAircraft.getPosition().latitude().value(CAngleUnit::deg()); - pos.lon = m_ownAircraft.getPosition().longitude().value(CAngleUnit::deg()); - pos.pitch = m_ownAircraft.getPitch().value(CAngleUnit::deg()); - pos.rating = Cvatlib_Network::pilotRating_Unknown; - pos.xpdrCode = m_ownTransponder.getTransponderCodeFormatted().toShort(); - switch (m_ownTransponder.getTransponderMode()) + if (this->m_loginMode == LoginAsObserver) { - case CTransponder::ModeC: pos.xpdrMode = Cvatlib_Network::xpndrMode_Normal; break; - case CTransponder::StateIdent: pos.xpdrMode = Cvatlib_Network::xpndrMode_Ident; break; - default: pos.xpdrMode = Cvatlib_Network::xpndrMode_Standby; break; + // Observer + Cvatlib_Network::ATCPosUpdate pos; + pos.facility = Cvatlib_Network::facilityType_Unknown; + pos.visibleRange = 10; // NM + pos.lat = m_ownAircraft.latitude().value(CAngleUnit::deg()); + pos.lon = m_ownAircraft.longitude().value(CAngleUnit::deg()); + pos.elevation = 0; + m_net->SendATCUpdate(pos); + } + else + { + // Normal / Stealth mode + Cvatlib_Network::PilotPosUpdate pos; + pos.altAdj = 0; // TODO: this needs to be calculated + pos.altTrue = m_ownAircraft.getAltitude().value(CLengthUnit::ft()); + pos.heading = m_ownAircraft.getHeading().value(CAngleUnit::deg()); + pos.pitch = m_ownAircraft.getPitch().value(CAngleUnit::deg()); + pos.bank = m_ownAircraft.getBank().value(CAngleUnit::deg()); + pos.lat = m_ownAircraft.latitude().value(CAngleUnit::deg()); + pos.lon = m_ownAircraft.longitude().value(CAngleUnit::deg()); + pos.groundSpeed = m_ownAircraft.getGroundSpeed().value(CSpeedUnit::kts()); + pos.rating = Cvatlib_Network::pilotRating_Unknown; + pos.xpdrCode = static_cast(m_ownAircraft.getTransponderCode()); + pos.xpdrMode = Cvatlib_Network::xpndrMode_Standby; + switch (m_ownAircraft.getTransponderMode()) + { + case CTransponder::ModeC: pos.xpdrMode = Cvatlib_Network::xpndrMode_Normal; break; + case CTransponder::StateIdent: pos.xpdrMode = Cvatlib_Network::xpndrMode_Ident; break; + default: pos.xpdrMode = Cvatlib_Network::xpndrMode_Standby; break; + } + m_net->SendPilotUpdate(pos); } - m_net->SendPilotUpdate(pos); } } catch (...) { exceptionDispatcher(Q_FUNC_INFO); } @@ -154,6 +176,11 @@ namespace BlackCore return m_fsdTextCodec->toUnicode(cstr); } + bool CNetworkVatlib::isConnected() const + { + return m_status == Cvatlib_Network::connStatus_Connected; + } + void exceptionDispatcher(const char *caller) { try @@ -193,14 +220,16 @@ namespace BlackCore { Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change callsign while still connected"); - m_callsign = toFSD(callsign); + m_ownAircraft.setCallsign(callsign); } void CNetworkVatlib::setRealName(const QString &name) { Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change name while still connected"); - m_realname = toFSD(name); + auto pilot = m_ownAircraft.getPilot(); + pilot.setRealName(name); + m_ownAircraft.setPilot(pilot); } void CNetworkVatlib::initiateConnection() @@ -210,13 +239,37 @@ namespace BlackCore try { m_status = Cvatlib_Network::connStatus_Connecting; // paranoia - Cvatlib_Network::PilotConnectionInfo info; - info.callsign = m_callsign.data(); - info.name = m_realname.data(); - info.rating = Cvatlib_Network::pilotRating_Student; //TODO - info.sim = Cvatlib_Network::simType_XPlane; //TODO - m_net->SetPilotLoginInfo(toFSD(m_server.getAddress()).data(), m_server.getPort(), - toFSD(m_server.getUser().getId()).data(), toFSD(m_server.getUser().getPassword()).data(), info); + + QByteArray callsign = toFSD(m_loginMode == LoginAsObserver ? + m_ownAircraft.getCallsign().getAsObserverCallsignString() : + m_ownAircraft.getCallsign().asString()); + QByteArray name = toFSD(m_ownAircraft.getPilot().getRealName()); + + if (this->m_loginMode == LoginAsObserver) + { + // Observer mode + Cvatlib_Network::ATCConnectionInfo info; + info.name = name.data(); + info.rating = Cvatlib_Network::atcRating_Obs; + info.callsign = callsign.data(); + m_net->SetATCLoginInfo(toFSD(m_server.getAddress()), m_server.getPort(), + toFSD(m_server.getUser().getId()), + toFSD(m_server.getUser().getPassword()), + info); + } + else + { + // normal scenario, also used in STEALTH + Cvatlib_Network::PilotConnectionInfo info; + info.callsign = callsign.data(); + info.name = name.data(); + info.rating = Cvatlib_Network::pilotRating_Student; //TODO + info.sim = Cvatlib_Network::simType_MSFS98; //TODO + m_net->SetPilotLoginInfo(toFSD(m_server.getAddress()), m_server.getPort(), + toFSD(m_server.getUser().getId()), + toFSD(m_server.getUser().getPassword()), + info); + } m_net->ConnectAndLogon(); } catch (...) @@ -235,9 +288,15 @@ namespace BlackCore catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } - void CNetworkVatlib::setOwnAircraftPosition(const BlackMisc::Aviation::CAircraftSituation &aircraft) + void CNetworkVatlib::setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft) { m_ownAircraft = aircraft; + } + + void CNetworkVatlib::setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude) + { + m_ownAircraft.setPosition(position); + m_ownAircraft.setAltitude(altitude); if (! m_updateTimer.isActive()) { @@ -245,19 +304,22 @@ namespace BlackCore } } - void CNetworkVatlib::setOwnAircraftTransponder(const BlackMisc::Aviation::CTransponder &xpdr) + void CNetworkVatlib::setOwnAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) { - m_ownTransponder = xpdr; + m_ownAircraft.setSituation(situation); + + if (! m_updateTimer.isActive()) + { + m_updateTimer.start(c_updateIntervalMsec); + } } - void CNetworkVatlib::setOwnAircraftFrequency(const BlackMisc::PhysicalQuantities::CFrequency &freq) + void CNetworkVatlib::setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2, + const BlackMisc::Aviation::CTransponder &xpdr) { - m_ownFrequency = freq; - } - - void CNetworkVatlib::setOwnAircraftIcao(const BlackMisc::Aviation::CAircraftIcao &icao) - { - m_ownAircraftIcao = icao; + m_ownAircraft.setCom1System(com1); + m_ownAircraft.setCom1System(com2); + m_ownAircraft.setTransponder(xpdr); } void CNetworkVatlib::sendTextMessages(const BlackMisc::Network::CTextMessageList &messages) @@ -268,8 +330,8 @@ namespace BlackCore CTextMessageList privateMessages = messages.getPrivateMessages(); foreach(BlackMisc::Network::CTextMessage message, privateMessages) { - if (message.getRecipient().isEmpty()) continue; - m_net->SendPrivateTextMessage(toFSD(message.getRecipient()), toFSD(message.getMessage())); + if (message.getRecipientCallsign().isEmpty()) continue; + m_net->SendPrivateTextMessage(toFSD(message.getRecipientCallsign()), toFSD(message.getMessage())); } CTextMessageList radioMessages = messages.getRadioMessages(); if (radioMessages.isEmpty()) return; @@ -353,7 +415,8 @@ namespace BlackCore { try { - m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(QString::number(m_ownFrequency.value(CFrequencyUnit::MHz()), 'f', 3))); + m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), + toFSD(QString::number(m_ownAircraft.getCom1System().getFrequencyActive().value(CFrequencyUnit::MHz()), 'f', 3))); } catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } @@ -362,7 +425,7 @@ namespace BlackCore { try { - m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign), toFSD(m_realname)); + m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign), toFSD(m_server.getUser().getRealName())); } catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } @@ -380,21 +443,21 @@ namespace BlackCore { try { - const QByteArray acTypeICAObytes = toFSD(m_ownAircraftIcao.getDesignator()); - const QByteArray airlineICAObytes = toFSD(m_ownAircraftIcao.getAirline()); - const QByteArray liverybytes = toFSD(m_ownAircraftIcao.getLivery()); + const QByteArray acTypeICAObytes = toFSD(m_ownAircraft.getIcaoInfo().getDesignator()); + const QByteArray airlineICAObytes = toFSD(m_ownAircraft.getIcaoInfo().getAirline()); + const QByteArray liverybytes = toFSD(m_ownAircraft.getIcaoInfo().getLivery()); std::vector keysValues; - if (!m_ownAircraftIcao.getDesignator().isEmpty()) + if (!m_ownAircraft.getIcaoInfo().getDesignator().isEmpty()) { keysValues.push_back(m_net->acinfo_Equipment); keysValues.push_back(acTypeICAObytes); } - if (m_ownAircraftIcao.hasAirline()) + if (m_ownAircraft.getIcaoInfo().hasAirline()) { keysValues.push_back(m_net->acinfo_Airline); keysValues.push_back(airlineICAObytes); } - if (m_ownAircraftIcao.hasLivery()) + if (m_ownAircraft.getIcaoInfo().hasLivery()) { keysValues.push_back(m_net->acinfo_Livery); keysValues.push_back(liverybytes); @@ -441,17 +504,24 @@ namespace BlackCore return static_cast(cbvar); } - void CNetworkVatlib::onConnectionStatusChanged(Cvatlib_Network *, Cvatlib_Network::connStatus, Cvatlib_Network::connStatus newStatus, void *cbvar) + CNetworkVatlib::ConnectionStatus convertConnectionStatus(Cvatlib_Network::connStatus status) + { + switch (status) + { + case Cvatlib_Network::connStatus_Idle: return CNetworkVatlib::Disconnected; + case Cvatlib_Network::connStatus_Connecting: return CNetworkVatlib::Connecting; + case Cvatlib_Network::connStatus_Connected: return CNetworkVatlib::Connected; + case Cvatlib_Network::connStatus_Disconnected: return CNetworkVatlib::Disconnected; + case Cvatlib_Network::connStatus_Error: return CNetworkVatlib::DisconnectedError; + } + qFatal("unrecognised connection status"); + return CNetworkVatlib::DisconnectedError; + } + + void CNetworkVatlib::onConnectionStatusChanged(Cvatlib_Network *, Cvatlib_Network::connStatus oldStatus, Cvatlib_Network::connStatus newStatus, void *cbvar) { cbvar_cast(cbvar)->m_status = newStatus; - switch (newStatus) - { - case Cvatlib_Network::connStatus_Idle: emit cbvar_cast(cbvar)->connectionStatusChanged(Disconnected); break; - case Cvatlib_Network::connStatus_Connecting: emit cbvar_cast(cbvar)->connectionStatusChanged(Connecting); break; - case Cvatlib_Network::connStatus_Connected: emit cbvar_cast(cbvar)->connectionStatusChanged(Connected); break; - case Cvatlib_Network::connStatus_Disconnected: emit cbvar_cast(cbvar)->connectionStatusChanged(Disconnected); break; - case Cvatlib_Network::connStatus_Error: emit cbvar_cast(cbvar)->connectionStatusChanged(Disconnected); break; - } + emit cbvar_cast(cbvar)->connectionStatusChanged(convertConnectionStatus(oldStatus), convertConnectionStatus(newStatus)); } void CNetworkVatlib::onTextMessageReceived(Cvatlib_Network *, const char *from, const char *to, const char *msg, void *cbvar) @@ -595,6 +665,15 @@ namespace BlackCore { auto &atis = cbvar_cast(cbvar)->m_atisParts[cbvar_cast(cbvar)->fromFSD(callsign)]; + if (lineType == Cvatlib_Network::atisLineType_VoiceRoom) + { + emit cbvar_cast(cbvar)->atisQueryVoiceRoomReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); + } + if (lineType == Cvatlib_Network::atisLineType_ZuluLogoff) + { + emit cbvar_cast(cbvar)->atisQueryLogoffTimeReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); + } + if (lineType == Cvatlib_Network::atisLineType_LineCount) { atis.setType(CInformationMessage::ATIS); @@ -603,7 +682,18 @@ namespace BlackCore } else { - atis.appendMessage("\n" + cbvar_cast(cbvar)->fromFSD(data)); + const QString fixed = cbvar_cast(cbvar)->fromFSD(data).trimmed(); + if (! fixed.isEmpty()) + { + // detect the stupid z1, z2, z3 placeholders + // TODO: Anything better as this stupid code here? + const QString test = fixed.toLower().remove(QRegExp("[\\n\\t\\r]")); + if (test == "z") return; + if (test.startsWith("z") && test.length() == 2) return; // z1, z2, .. + if (test.length() == 1) return; // sometimes just z + + atis.appendMessage("\n" + cbvar_cast(cbvar)->fromFSD(data)); + } } } @@ -612,36 +702,41 @@ namespace BlackCore //TODO } - void CNetworkVatlib::onErrorReceived(Cvatlib_Network *, Cvatlib_Network::error type, const char *msg, const char *data, void *cbvar) + void CNetworkVatlib::onErrorReceived(Cvatlib_Network *, Cvatlib_Network::error type, const char *msgData, const char *data, void *cbvar) { + QString msg; + switch (type) { - case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; goto terminate; - case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; goto terminate; - case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; goto terminate; - case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server does not support our protocol version"; goto terminate; - case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate; - case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; goto terminate; - case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; goto terminate; - case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate; - case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; goto terminate; + case Cvatlib_Network::error_CallsignTaken: msg = "The requested callsign is already taken"; goto terminate; + case Cvatlib_Network::error_CallsignInvalid: msg = "The requested callsign is not valid"; goto terminate; + case Cvatlib_Network::error_CIDPasswdInvalid: msg = "Wrong user ID or password"; goto terminate; + case Cvatlib_Network::error_ProtoVersion: msg = "This server does not support our protocol version"; goto terminate; + case Cvatlib_Network::error_LevelTooHigh: msg = "You are not authorized to use the requested pilot rating"; goto terminate; + case Cvatlib_Network::error_ServerFull: msg = "The server is full"; goto terminate; + case Cvatlib_Network::error_CIDSuspended: msg = "Your user account is suspended"; goto terminate; + case Cvatlib_Network::error_InvalidPosition: msg = "You are not authorized to use the requested pilot rating"; goto terminate; + case Cvatlib_Network::error_SoftwareNotAuthorized: msg = "This client software has not been authorized for use on this network"; goto terminate; - case Cvatlib_Network::error_Ok: break; - case Cvatlib_Network::error_Syntax: qWarning() << "Malformed packet: Syntax error: " << cbvar_cast(cbvar)->fromFSD(data); break; - case Cvatlib_Network::error_SourceInvalid: qDebug() << "Server: source invalid " << cbvar_cast(cbvar)->fromFSD(data); break; - case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break; - case Cvatlib_Network::error_NoFP: qDebug() << "Server: no flight plan"; break; - case Cvatlib_Network::error_NoWeather: qDebug() << "Server: requested weather profile does not exist"; break; + case Cvatlib_Network::error_Ok: msg = "OK"; break; + case Cvatlib_Network::error_Syntax: msg = "Malformed packet: Syntax error: "; msg.append(cbvar_cast(cbvar)->fromFSD(data)); break; + case Cvatlib_Network::error_SourceInvalid: msg = "Server: source invalid "; msg.append(cbvar_cast(cbvar)->fromFSD(data)); break; + case Cvatlib_Network::error_CallsignNotExists: msg = "Shim lib: "; msg.append(cbvar_cast(cbvar)->fromFSD(msgData)).append(" (").append(cbvar_cast(cbvar)->fromFSD(data)).append(")"); break; + case Cvatlib_Network::error_NoFP: msg = "Server: no flight plan"; break; + case Cvatlib_Network::error_NoWeather: msg = "Server: requested weather profile does not exist"; break; // we have no idea what these mean case Cvatlib_Network::error_Registered: - case Cvatlib_Network::error_InvalidControl: qWarning() << "Server: " << cbvar_cast(cbvar)->fromFSD(msg); break; + case Cvatlib_Network::error_InvalidControl: msg = "Server: "; msg.append(cbvar_cast(cbvar)->fromFSD(msgData)); break; default: qFatal("VATSIM shim library: %s (error %d)", msg, type); goto terminate; } + emit cbvar_cast(cbvar)->statusMessage(BlackMisc::CStatusMessage(BlackMisc::CStatusMessage::TypeTrafficNetwork, BlackMisc::CStatusMessage::SeverityInfo, msg)); return; + terminate: + emit cbvar_cast(cbvar)->statusMessage(BlackMisc::CStatusMessage(BlackMisc::CStatusMessage::TypeTrafficNetwork, BlackMisc::CStatusMessage::SeverityError, msg)); emit cbvar_cast(cbvar)->terminate(); } diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h index edda31c13..9eb8bb323 100644 --- a/src/blackcore/network_vatlib.h +++ b/src/blackcore/network_vatlib.h @@ -27,9 +27,18 @@ namespace BlackCore Q_OBJECT public: - CNetworkVatlib(QObject *parent = nullptr); + enum LoginMode + { + LoginNormal = 0, + LoginAsObserver, + LoginStealth + }; + + CNetworkVatlib(LoginMode loginMode = LoginNormal, QObject *parent = nullptr); virtual ~CNetworkVatlib(); + bool isConnected() const; + public: // INetwork slots overrides // Network @@ -53,10 +62,11 @@ namespace BlackCore // Aircraft virtual void requestAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign); virtual void sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign); - virtual void setOwnAircraftPosition(const BlackMisc::Aviation::CAircraftSituation &aircraft); - virtual void setOwnAircraftTransponder(const BlackMisc::Aviation::CTransponder &xpdr); - virtual void setOwnAircraftFrequency(const BlackMisc::PhysicalQuantities::CFrequency &freq); - virtual void setOwnAircraftIcao(const BlackMisc::Aviation::CAircraftIcao &icao); + virtual void setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft); + virtual void setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude); + virtual void setOwnAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + virtual void setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2, + const BlackMisc::Aviation::CTransponder &xpdr); // ATC virtual void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign); @@ -114,8 +124,10 @@ namespace BlackCore private: QScopedPointer m_net; + LoginMode m_loginMode; Cvatlib_Network::connStatus m_status; BlackMisc::Network::CServer m_server; + BlackMisc::Aviation::CAircraft m_ownAircraft; QMap m_atisParts; QTimer m_processingTimer; @@ -123,14 +135,6 @@ namespace BlackCore static int const c_processingIntervalMsec = 100; static int const c_updateIntervalMsec = 5000; static int const c_logoffTimeoutSec = 5; - - QByteArray m_callsign; - QByteArray m_realname; - BlackMisc::Aviation::CAircraftSituation m_ownAircraft; - BlackMisc::Aviation::CTransponder m_ownTransponder; - BlackMisc::PhysicalQuantities::CFrequency m_ownFrequency; - BlackMisc::Aviation::CAircraftIcao m_ownAircraftIcao; - QTextCodec *m_fsdTextCodec; }; diff --git a/tests/blackcore/testnetwork.cpp b/tests/blackcore/testnetwork.cpp index 808b80058..3dc24cf45 100644 --- a/tests/blackcore/testnetwork.cpp +++ b/tests/blackcore/testnetwork.cpp @@ -18,20 +18,35 @@ void BlackCoreTest::CTestNetwork::networkTest(BlackCore::INetwork *net) Expect e(net); EXPECT_UNIT(e) - .send(&INetwork::setServer, CServer("", "", "vatsim-germany.org", 6809, CUser("guest", "", "", "guest"))) - .send(&INetwork::setCallsign, "BLACK") - .send(&INetwork::initiateConnection) - .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus s) { QVERIFY(s == INetwork::Connecting); qDebug() << "CONNECTING"; }) - .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus s) { QVERIFY(s == INetwork::Connected); qDebug() << "CONNECTED"; }) - .wait(10); + .send(&INetwork::setServer, CServer("", "", "vatsim-germany.org", 6809, CUser("guest", "", "", "guest"))) + .send(&INetwork::setCallsign, "BLACK") + .send(&INetwork::initiateConnection) + .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus, INetwork::ConnectionStatus newStatus) + { + QVERIFY(newStatus == INetwork::Connecting); + qDebug() << "CONNECTING"; + } + ).expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus, INetwork::ConnectionStatus newStatus) + { + QVERIFY(newStatus == INetwork::Connected); + qDebug() << "CONNECTED"; + } + ).wait(10); EXPECT_UNIT(e) - .send(&INetwork::ping, "server") - .expect(&INetwork::pong, [](CCallsign callsign, PhysicalQuantities::CTime elapsedTime) { qDebug() << "PONG" << callsign << elapsedTime; }) - .wait(10); + .send(&INetwork::ping, "server") + .expect(&INetwork::pong, [](CCallsign callsign, PhysicalQuantities::CTime elapsedTime) + { + qDebug() << "PONG" << callsign << elapsedTime; + } + ).wait(10); EXPECT_UNIT(e) - .send(&INetwork::terminateConnection) - .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus s) { QVERIFY(s == INetwork::Disconnected); qDebug() << "DISCONNECTED"; }) - .wait(10); + .send(&INetwork::terminateConnection) + .expect(&INetwork::connectionStatusChanged, [](INetwork::ConnectionStatus s) + { + QVERIFY(s == INetwork::Disconnected); + qDebug() << "DISCONNECTED"; + } + ).wait(10); }