/** * Convert Json from WLS to internal telegrams * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-09-26 */ #include "wls_handler_rx.h" #include "wls_dispatcher.h" #include #include #include #include #include namespace WlsTetra { WlsHandlerRx::WlsHandlerRx(const std::shared_ptr &recvFromTabCb, WlsDispatcher *dispatcher) : m_rxHandler(recvFromTabCb) , m_dispatcher(dispatcher) , m_bWarnedOnce(false) , m_logger(getLogger("WlsHandlerRx")) {} bool WlsHandlerRx::handleTelegram(const QByteArray &baJson) { using namespace TrainingAreaBase::TetraIcd; if (baJson.isEmpty()) return false; const QJsonObject obj = QJsonDocument::fromJson(baJson).object(); TRACE_LOG(m_logger) << "incoming telegram: " << baJson; // const QJsonValue sendCounter = obj.value(QStringLiteral("counter")); // if (!sendCounter.isUndefined()) // { // if (!sendCounter.isDouble()) // return false; // recvCounter = sendCounter.toInt(-1); // DEBUG_LOG(m_logger) << "Incoming telegram with Id " << obj.value(QStringLiteral("type")).toString(); // if (recvCounter < 0) // return false; // } 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(); try { switch (typeId.toInt()) { case Constraints::id(): // 21 rxData(PositionReport::fromJson(data)); break; case Constraints::id(): // 2013 m_dispatcher->onWlsExternalConnectionStateChanged(ProxyConnectionState::fromJson(data).connectedToSystem); break; case Constraints::id(): // 3003 sfmData(WlsBinarySfmData::fromJson(data)); break; case Constraints::id(): // 3004 { const auto tele = WlsParticipantsConnectionState::fromJson(data); emit participantConnectionState(tele.equipmentNumber, tele.dataCommunicationPossible); break; } } } catch (const std::exception &e) { WARNING_LOG(m_logger) << "Could not parse json: " << e.what() << " (" << baJson << ")"; return false; } return true; } void WlsHandlerRx::participantLicenseChange(const TrainingAreaBase::TetraIcd::ParticipantLicenseChange &lc) { if (lc.equipmentNumber <= 0) { return; } switch (lc.licenseState) { case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Licensed: m_licensedEquipmentNumbers.insert(lc.equipmentNumber); break; case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Rejected: case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unlicense: m_licensedEquipmentNumbers.remove(lc.equipmentNumber); break; case TrainingAreaBase::TetraIcd::ParticipantLicenseState::Unknown: Q_ASSERT(false); break; } } template <> void WlsHandlerRx::rxData(const TrainingAreaBase::TetraIcd::RequestBroadcastTelegrams &data) { emit m_dispatcher->broadcastTelegramsRequest(data.header.equipmentNumber, data.broadcastIndex, data.resetCounter); } template static inline T toSpecialized(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele) { return *(static_cast(tabTele)); } bool WlsHandlerRx::handleTelegram(TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele) { using namespace TrainingAreaBase::TetraIcd; switch (tabTele->id()) { // Telegrams converted from WlsBinarySfmData case Constraints::id(): // 2 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 7 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 11 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 12 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 41 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 43 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 44 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 45 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 52 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 53 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 55 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 56 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 61 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 71 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 82 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 185 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 200 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 202 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 205 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 210 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 213 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 231 rxData(toSpecialized(tabTele)); break; case Constraints::id(): // 233 rxData(toSpecialized(tabTele)); break; default: ERROR_LOG(m_logger) << "WlsHandlerRx::handleTelegram no Handler for " << tabTele->id(); return false; } return true; } class RadioTelegram : public N_CoPrtCnv::CoPrtCnvRadioTelegram { public: RadioTelegram(const QByteArray &data) : N_CoPrtCnv::CoPrtCnvRadioTelegram(data) {} uint16_t getPayloadSize() const override { return m_data.size() - CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH; } }; void WlsHandlerRx::sfmData(const TrainingAreaBase::TetraIcd::WlsBinarySfmData &data) { if (data.payload.size() < 2) { ERROR_LOG(m_logger) << "Invalid binary data from WLS: " << QJsonDocument(data.toJson()).toJson(QJsonDocument::Compact); return; } using namespace N_CoPrtCnv; const int offset = CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH; QByteArray ba(data.payload.size() + offset, Qt::Uninitialized); memcpy(&ba.data()[offset], data.payload.data(), data.payload.size()); const RadioTelegram radio(ba); TrainingAreaBase::TetraIcd::TrainingAreaTelegram *tabTele = CoPrtCnvTelegramConverter::convertToTabTele(&radio); if (!tabTele) { WARNING_LOG(m_logger) << "Can not convert binary sfm data to a valid tetra telegram - ignoring (" << data.header.equipmentNumber << "): " << QByteArray::fromRawData(reinterpret_cast(data.payload.data()), data.payload.size()).toHex(); return; } handleTelegram(tabTele); delete tabTele; } template void WlsHandlerRx::rxData(const T &data) { if (!m_rxHandler) { if (!m_bWarnedOnce) { ERROR_LOG(m_logger) << "No RecvFromTab available"; m_bWarnedOnce = true; } return; } if (data.header.equipmentNumber != 0 && data.id() != TrainingAreaBase::TetraIcd::BITE_MELDUNG2 && !m_licensedEquipmentNumbers.contains(data.header.equipmentNumber)) return; emit m_dispatcher->wlsTelegramReceived(&data); return m_rxHandler->rxData(data); } } // namespace WlsTetra