/** * @RDE_HEADER@ * JsonHandlerRx for AdlerJson Plugin * $Id: hla_handler_rx.cpp 62899 2024-05-29 11:08:50Z ewert_j $ * $HeadURL: svn://slssvn/TDS/branches/product/features/ufom/Lts/Proxies/TrainingAreaBase/Plugins/AdlerJson/hla_handler_rx.cpp $ * $Author: ewert_j $ * Created by Julius Ewert, ESIM, 2024-03-20 */ #include "json_handler_rx.h" #include "aes_handler.h" #include "json_dispatcher.h" #include "ppm_handler.h" #include "telegrams.h" #include namespace AdlerJson { JsonHandlerRx::JsonHandlerRx(const std::shared_ptr &recvFromTabCb, const std::shared_ptr &sendToTabCb, JsonDispatcher *dispatcher, AesHandler *aesHandler, PpmHandler *ppmHandler) : m_rxHandler(recvFromTabCb) , m_txHandler(sendToTabCb) // std::static_pointer_cast(sendToTabCb)) , m_dispatcher(dispatcher) , m_bWarnedOnce(false) , m_bWarnedOnceTx(false) , m_aesHandler(aesHandler) , m_ppmHandler(ppmHandler) , m_logger(getLogger("JsonHandlerRx")) { } bool JsonHandlerRx::handleTelegram(int wsId, const QJsonObject &telegram, int &errorcode) { errorcode = 0; using namespace TrainingAreaBase::TetraIcd; if (!telegram.contains(JsonKeys::TYPE_ID())) { ERROR_LOG(m_logger) << "telegram not contains typeId"; } const int typeId = telegram[JsonKeys::TYPE_ID()].toInt(); const QString typeName = telegram[JsonKeys::TYPE()].toString(); const QString uuid = telegram[JsonKeys::UUID_()].toString(); const QString referenceUuid = telegram[JsonKeys::REFERENCE_UUID()].toString(); INFO_LOG(m_logger) << "[handleTelegram] typeId=" << typeId << " typeName=" << typeName << " uuid=" << uuid << " referenceUuid=" << referenceUuid; try { switch (typeId) { case AdlerJson::TelegramIds::EX_REGISTRATION_REQUEST(): // EX-Anmeldung { QJsonObject dataObj = telegram[JsonKeys::DATA()].toObject(); int partyId = dataObj.value(JsonKeys::PARTY_ID()).toInt(0); QString saaName = telegram[JsonKeys::SENDER()].toString(); QString szenarName = dataObj.value(JsonKeys::SZENAR()).toString(); bool isVerbund = dataObj.value(JsonKeys::ADLER_VERBUND()).toBool(); m_dispatcher->onSAARegistration(wsId, partyId, saaName, szenarName, isVerbund, uuid); WARNING_LOG(m_logger) << "On Register ------------------- partyId= " << partyId << ", saaName= " << saaName << ", szenarName= " << szenarName << ", isVerbund= " << isVerbund << ", wsId= " << wsId; break; } case TelegramIds::EX_DEREGISTRATION_REQUEST(): // EX-Abmeldung { const int partyId = telegram[JsonKeys::DATA()].toObject().value(JsonKeys::PARTY_ID()).toInt(0); m_dispatcher->onSAADeregistration(wsId, partyId); WARNING_LOG(m_logger) << "[EX_DEREGISTRATION_REQUEST] EX-Abmeldung -------------------------------------"; break; } case TelegramIds::EX_CONNECTION_TEST_REQUEST(): // EX-Verbindungsanfrage { DEBUG_LOG(m_logger) << "[EX_CONNECTION_TEST_REQUEST] EX-Verbindungsanfrage -------------------------------------"; m_dispatcher->onSAAConnectionTest(wsId, uuid); break; } case TelegramIds::EX_STATUS(): // EX-Status { WARNING_LOG(m_logger) << "[EX_STATUS] EX-Status -------------------------------------"; auto data = telegram[JsonKeys::DATA()]; const QString status = data.toObject().value(JsonKeys::STATUS()).toString(QStringLiteral("")); EXStatus exStatus; exStatus.status = strToSzenarstatus(status); m_dispatcher->onSAAStatus(wsId, exStatus); break; } case TelegramIds::EX_TQ(): // Technische Quittierung { WARNING_LOG(m_logger) << "[EX_TQ] Technische Quittierung -------------------------------------"; const auto data = telegram[JsonKeys::DATA()].toObject(); bool bOk = true; TechnischeDaten technischeDaten; AdlerJson::technischeDatenFromJson(data, technischeDaten, bOk); m_dispatcher->onSAAExceptionStatus(wsId, technischeDaten); break; } case TelegramIds::EX_FIRE(): // EX-FQ(FN) Feuern { WARNING_LOG(m_logger) << "[EX-FQ(FN)] EX-Feuern -------------------------------------"; auto data = telegram[JsonKeys::DATA()].toObject(); bool bOk = true; Feuerkampfdaten exFire; feuerkampfdatenFromJson(data, exFire, bOk); // send to AES m_aesHandler->handleEXFire(exFire, wsId); break; } case TelegramIds::EX_AWES_PLANNING(): // EX-FQ(BA-BB-FK) Wirkfeldplanung { WARNING_LOG(m_logger) << "[EX_AWES_PLANNING] EX-FQ(BA-BB-FK) Wirkfeldplanung"; auto data = telegram[JsonKeys::DATA()].toObject(); WirkfeldplanungData wirkfeldplanungData; bool bOk = true; wirkfeldplanungDataFromJson(data, wirkfeldplanungData, bOk); DEBUG_LOG(m_logger) << "\n-------------------" << "\nwirkfeldplanungData" << "\n dauer: " << wirkfeldplanungData.dauer << "\n abfeuerungsArt: " << static_cast(wirkfeldplanungData.abfeuerungsArt) << "\n feuerkampfReferenz: '" << wirkfeldplanungData.feuerkampfReferenz << "'" << "\n verein: '" << wirkfeldplanungData.feuerkommando.verein << "'" << "\n bOk: " << bOk << "\n-------------------"; m_aesHandler->handleEffectCluster(wirkfeldplanungData, wsId); break; } case TelegramIds::EX_POSITION_REPORT_WEAPON(): // Only sent by SAA ( Ex-SQ(WS) Stellungsmeldung Waffensystem) { DEBUG_LOG(m_logger) << "[EX_POSITION_REPORT_WEAPON] Ex-SQ(WS) Stellungsmeldung Waffensystem"; auto data = telegram[JsonKeys::DATA()].toObject(); Waffensystemdaten exSQWS; bool bOk = true; waffensystemdatenFromJson(data, exSQWS, bOk); if (!bOk) { ERROR_LOG(m_logger) << "Received Ex-SQ(WS) but couldn't parse the jsondata "; break; } m_dispatcher->onSAASQWS(wsId, exSQWS); break; } case TelegramIds::EX_POSITION_REPORT_FIRE(): // Only sent by SAA ( Ex-SQ(FS) Stellungsmeldung Feuerstellung) { DEBUG_LOG(m_logger) << "[EX_POSITION_REPORT_FIRE] Ex-SQ(FS) Stellungsmeldung Feuerstellung"; auto data = telegram[JsonKeys::DATA()].toObject(); Feuerstellungsdaten exSQFS; bool bOk = true; feuerstellungsdatenFromJson(data, exSQFS, bOk); if (!bOk) { ERROR_LOG(m_logger) << "Received Ex-SQ(FS) but couldn't parse the jsondata "; break; } m_dispatcher->onSAASQFS(wsId, exSQFS); break; } case TelegramIds::EX_POSITION_REPORT_LOADING_PLACE(): // sent by SAA+EXCON ( EX-SQ(LP)Stellungsmeldung Ladeplatz) { DEBUG_LOG(m_logger) << "[EX_POSITION_REPORT_LOADING_PLACE] EX-SQ(LP)Stellungsmeldung Ladeplatz"; auto data = telegram[JsonKeys::DATA()].toObject(); Ladeplatzdaten exSQLP; bool bOk = true; ladeplatzdatenFromJson(data, exSQLP, bOk); if (!bOk) { ERROR_LOG(m_logger) << "Received Ex-SQ(LP) but couldn't parse the jsondata "; break; } m_dispatcher->onSAASQLP(wsId, exSQLP); break; } case TelegramIds::EX_FLUGBAHNDATEN(): // sent by SAA (EX-Flugbahndaten) { DEBUG_LOG(m_logger) << "[EX_FLUGBAHNDATEN] EX-Flugbahndaten"; auto data = telegram[JsonKeys::DATA()].toObject(); Flugbahndaten flugbahndaten; bool bOk = true; flugbahndatenFromJson(data, flugbahndaten, bOk); if (!bOk) { ERROR_LOG(m_logger) << "Received EX-Flugbahndaten but couldn't parse the jsondata "; break; } DEBUG_LOG(m_logger) << "Vor onSAATrajectoryData wsId=" << wsId; if (static_cast(flugbahndaten.fehlercode) == 0) m_dispatcher->onSAATrajectoryData(wsId, flugbahndaten, referenceUuid); else errorcode = static_cast(flugbahndaten.fehlercode); break; } case TelegramIds::EX_GUIDING_LINES(): // sent by SAA ( EX-HQ(K) Koordinierungsmassnahmen) { DEBUG_LOG(m_logger) << "[EX_GUIDING_LINES] EX-HQ Koordinierungsmassnahmen"; auto data = telegram[JsonKeys::DATA()].toObject(); const QString artStr = data.value(JsonKeys::ART()).toString(QStringLiteral("Koordinierungsmassnahmen")); Koordinierungsdaten koordinierungsdaten; bool bOk = true; koordinierungsdatenFromJson(data, koordinierungsdaten, bOk); if (koordinierungsdaten.name.isEmpty()) koordinierungsdaten.name = QString(QStringLiteral("%1 - %2")).arg(typeName).arg(artStr); else koordinierungsdaten.name = QString(QStringLiteral("%1 - %2")).arg(typeName).arg(koordinierungsdaten.name); m_dispatcher->onSAAHXGuidingLines(wsId, koordinierungsdaten); break; } case TelegramIds::EX_GUIDING_LINES_AND_BOUNDARIES(): // sent by SAA ( EX-HQ(G)Fuehrungslinien und Grenzen) { DEBUG_LOG(m_logger) << "[EX_GUIDING_LINES_AND_BOUNDARIES] EX-HQ(G)Fuehrungslinien und Grenzen "; auto data = telegram[JsonKeys::DATA()].toObject(); const QString artStr = data.value(JsonKeys::ART()).toString(QStringLiteral("Fuehrungslinien und Grenzen")); Fuehrungsdaten fuehrungsdaten; bool bOk = true; fuehrungsdatenFromJson(data, fuehrungsdaten, bOk); if (fuehrungsdaten.name.isEmpty()) fuehrungsdaten.name = QString(QStringLiteral("%1 - %2")).arg(typeName).arg(artStr); else fuehrungsdaten.name = QString(QStringLiteral("%1 - %2")).arg(typeName).arg(fuehrungsdaten.name); m_dispatcher->onSAAHXGuidingLinesAndBoundaries(wsId, fuehrungsdaten); break; } case TelegramIds::EX_FIRE_HALT(): // sent by SAA (EX-FH Feuerhalt) { WARNING_LOG(m_logger) << "[EX_FIRE_HALT] Feuerhalt"; auto data = telegram[QStringLiteral("data")].toObject(); bool bOk = true; FeuerHaltDaten feuerhaltdaten; feuerHaltDatenFromJson(data, feuerhaltdaten, bOk); m_dispatcher->onSSAEXFIREHALT(wsId, feuerhaltdaten); break; } case TelegramIds::EX_DONT_FIRE(): // send by SAA EX-FQ(nFN) { WARNING_LOG(m_logger) << "[EX_DONT_FIRE] Dont Fire"; auto data = telegram[QStringLiteral("data")].toObject(); bool bOk = true; Feuerkampfdaten feuerkampfdaten; exNichtFeuernFromJson(data, feuerkampfdaten, bOk); m_aesHandler->handleEXDontFire(feuerkampfdaten, wsId); break; } default: { WARNING_LOG(m_logger) << "Cant handle Telegram typeId=" << typeId; } } } catch (const std::exception &e) { WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << ")"; return false; } return true; } bool JsonHandlerRx::handleTelegram(const QByteArray &baJson) { DEBUG_LOG(m_logger) << "JsonHandlerRx::handleTelegram"; if (baJson.isEmpty()) return false; const QJsonObject obj = QJsonDocument::fromJson(baJson).object(); const QJsonValue typeId = obj.value(QStringLiteral("typeId")); if (!typeId.isDouble()) { ERROR_LOG(m_logger) << "Can not read type id: " << baJson; return false; } const QJsonObject data = obj.value(QStringLiteral("data")).toObject(); if (typeId.toInt() != 21) ERROR_LOG(m_logger) << "Telegram before filter: " << baJson; try { QJsonValue header = data[QStringLiteral("header")]; QJsonObject obj = header.toObject(); ERROR_LOG(m_logger) << "Telegram header: " << obj.count(); if (!obj.isEmpty()) { int eqNo = obj[QStringLiteral("equipmentNumber")].toInt(0); if (eqNo <= 0) return false; if (!checkExercise(eqNo)) return false; } if (typeId.toInt() != 21) ERROR_LOG(m_logger) << "Telegram after filter: " << baJson; } catch (const std::exception &e) { WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << baJson << ")"; return false; } return true; } bool JsonHandlerRx::checkExercise(int equipmentNumber) const { return m_ppmHandler->isEqNumberInExercise(equipmentNumber); } template void JsonHandlerRx::rxData(const T &data) { if (!m_rxHandler) { if (!m_bWarnedOnce) { ERROR_LOG(m_logger) << "No RecvFromTab available"; m_bWarnedOnce = true; } return; } emit m_dispatcher->jsonTelegramReceived(&data); return m_rxHandler->rxData(data); } template void JsonHandlerRx::txData(const T &data) { if (!m_txHandler) { if (!m_bWarnedOnceTx) { ERROR_LOG(m_logger) << "No RecvFromTab available"; m_bWarnedOnceTx = true; } return; } emit m_dispatcher->jsonTelegramReceived(&data); m_txHandler->txData(data); } } // namespace AdlerJson