#include "cnr_frequency_planning_helper.h" #include #include #include #include #include // Todo: Better tr() ? #include namespace AudioVideoManagement { template T fromJson(const QByteArray &json) { QJsonParseError jError; QJsonDocument doc(QJsonDocument::fromJson(json, &jError)); if (jError.error) return {}; QJsonObject obj = doc.object(); return T::fromJson(obj); } // Todo: // // FreqPlanningDataSet ist nur noch ein pro FreqPlanningData vorhanden. Also integrieren in die Relation. // DB und DDS Typen anpassen // Die Properties einer FreqPlanningData(Set) sind ein Array (REL) (VHF/UHF/HF) // wie in der Methode unter diesem Kommentar (bei dem die RadioSpecificaJSON schon mit rein geht!), // siehe avm_edit_frequency_planning_resource_dialog.cpp:120 // Aus dieser einen Zeile müssen dann im Übersichtsdialog entweder ein Eintrag oder (mindestens) 3 Einträge (REL) gemacht werden. // Die RadioSpecificaHelper also um Hilfsmethoden erweitern, damit man passende Objekte bekommt. // Vielleicht die drei items Name, FreqBand, RadioStation ID gleich mit in die Specifica, bzw. von was ableiten, dass das beinhaltet! // Method to obtain all "FrequencySetDataId" from an QJsonObject QJsonObject frequencyPlanningJson(QJsonObject obj, const QString &name, FrequencyBand freqBand, int radioStationId) { obj.insert(QStringLiteral("Name"), name); obj.insert(QStringLiteral("FrequencyBand"), freqBand.underlying()); obj.insert(QStringLiteral("RadioStationId"), radioStationId); return obj; } bool RadioCircuitHF::isValid() const { if ((modulationType != ModulationType::AM && modulationType != ModulationType::FM) || (channelSpacing != ChannelSpacingHF::CS_100_Hz) || frequency < FREQ_MIN || frequency > FREQ_MAX || squelch < (SQUELCH_MIN-1) || squelch > SQUELCH_MAX ) return false; return true; } QJsonObject RadioCircuitHF::toJson() const { QJsonObject obj; obj.insert(QStringLiteral("ModulationType"), modulationType.underlying()); obj.insert(QStringLiteral("ChannelSpacing"), channelSpacing.underlying()); obj.insert(QStringLiteral("Frequency"), frequency); obj.insert(QStringLiteral("Squelch"), squelch); return obj; } RadioCircuitHF* RadioCircuitHF::fromJson(const QJsonObject &obj) { RadioCircuitHF *spec = new RadioCircuitHF(); spec->modulationType = static_cast(obj.value(QStringLiteral("ModulationType")).toInt(-1)); spec->channelSpacing = static_cast(obj.value(QStringLiteral("ChannelSpacing")).toInt()); spec->frequency = obj.value(QStringLiteral("Frequency")).toInt(); spec->squelch = obj.value(QStringLiteral("Squelch")).toInt(-1); if (spec->isValid()) return spec; return nullptr; } bool RadioCircuitUHF::isValid() const { if ((modulationType != ModulationType::AM && modulationType != ModulationType::FM) || (channelSpacing != ChannelSpacing::CS_8_33_kHz && channelSpacing != ChannelSpacing::CS_12_50_kHz && channelSpacing != ChannelSpacing::CS_25_00_kHz) || frequency < FREQ_MIN || frequency > FREQ_MAX || ((squelchDB < SQUELCH_MIN || squelchDB > SQUELCH_MAX) && squelchDB != 0) // 0 or Min modulationType = static_cast(obj.value(QStringLiteral("ModulationType")).toInt(-1)); spec->channelSpacing = static_cast(obj.value(QStringLiteral("ChannelSpacing")).toInt()); spec->frequency = obj.value(QStringLiteral("Frequency")).toInt(); spec->squelchDB = obj.value(QStringLiteral("Squelch")).toInt(-1); auto clipper = obj.value(QStringLiteral("Clipper")); if (clipper.isUndefined() || !clipper.isBool()) return nullptr; spec->clipper = clipper.toBool(); auto agc = obj.value(QStringLiteral("AGC")); if (agc.isUndefined() || !agc.isBool()) return {}; spec->agc = agc.toBool(); if (spec->isValid()) return spec; return nullptr; } QJsonObject RadioCircuitVHF::toJson() const { QJsonObject obj; obj.insert(QStringLiteral("OperatingMode"), operatingMode.underlying()); obj.insert(QStringLiteral("FrequencySetDataId"), freqSetDataId); obj.insert(QStringLiteral("PilotTone"), pilotTone); return obj; } RadioCircuitVHF* RadioCircuitVHF::fromJson(const QJsonObject &obj) { RadioCircuitVHF *spec = new RadioCircuitVHF(); spec->operatingMode = static_cast(obj.value(QStringLiteral("OperatingMode")).toInt(-1)); spec->freqSetDataId = obj.value(QStringLiteral("FrequencySetDataId")).toInt(); auto pilotTone = obj.value(QStringLiteral("PilotTone")); if (pilotTone.isUndefined() || !pilotTone.isBool()) return nullptr; spec->pilotTone = pilotTone.toBool(); if (spec->isValid()) return spec; return nullptr; } QString RadioCircuitHF::toString() const { return QCoreApplication::translate("AVM", "Frequency: %1, ModulationType: %2, ChannelSpacing: %3, Squelch: %4") .arg(frequency) .arg(AudioVideoManagement::toString(modulationType)) .arg(100) .arg(squelch); } QString RadioCircuitUHF::toString() const { return QCoreApplication::translate("AVM", "Frequency: %1, ModulationType: %2, ChannelSpacing: %3, Squelch: %4, Clipper: %5, AGC: %6") .arg(frequency) .arg(AudioVideoManagement::toString(modulationType)) .arg(AudioVideoManagement::toString(channelSpacing)) .arg(squelchDB) .arg(clipper) .arg(agc); } QString RadioCircuitVHF::toString() const { return QCoreApplication::translate("AVM", "OperatingMode: %1, PilotTone: %2") .arg(AudioVideoManagement::toString(operatingMode)) .arg(pilotTone); } QVector fromJson(const std::string &json) { QVector vec; QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(json), &err); if(err.error != QJsonParseError::NoError) return {}; QJsonArray arr = doc.object().value(QStringLiteral("subCircuits")).toArray(); // Todo? Check if values are correctly filled and values are present... // maybe VHF is missing a frequencysetid : show ErrorMessage? for(const QJsonValue &val : qAsConst(arr)) { RadioCircuit *rc = nullptr; const QJsonObject obj = val.toObject(); FrequencyBand ft = static_cast(obj[QStringLiteral("FrequencyBand")].toInt()); switch (ft.underlying()) { case FrequencyBand_def::HF: rc = RadioCircuitHF::fromJson(obj); break; case FrequencyBand_def::UHF: rc = RadioCircuitUHF::fromJson(obj); break; case FrequencyBand_def::VHF: rc = RadioCircuitVHF::fromJson(obj); break; case FrequencyBand_def::REL: default: break; } if(rc) { rc->freqBand = ft; rc->name = obj[QStringLiteral("Name")].toString(); rc->radioStationId = obj[QStringLiteral("RadioStationId")].toInt(); vec << rc; } } return vec; } QSet frequencySetDataIds(const std::string &frequencyPlanDataProperties) { QSet set; QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(frequencyPlanDataProperties), &err); if(err.error != QJsonParseError::NoError) return {}; QJsonArray arr = doc.object().value(QStringLiteral("subCircuits")).toArray(); // Todo? Check if values are correctly filled and values are present... for(const QJsonValue &val : qAsConst(arr)) { const QJsonObject obj = val.toObject(); FrequencyBand ft = static_cast(obj[QStringLiteral("FrequencyBand")].toInt()); switch (ft.underlying()) { case FrequencyBand_def::VHF: { RadioCircuitVHF *rcVhf = RadioCircuitVHF::fromJson(obj); if(!rcVhf) break; set << rcVhf->frequencySetDataId(); delete rcVhf; break; } case FrequencyBand_def::UHF: case FrequencyBand_def::HF: default: break; } } return set; } bool isReadOnly(const std::string &frequencyPlanDataProperties) { QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(frequencyPlanDataProperties), &err); if(err.error != QJsonParseError::NoError) return false; return doc.object().value(QStringLiteral("readOnly")).toBool(); } bool isAkwMode(RcOperatingMode mode) { return mode == RcOperatingMode::AkwEncEccm || mode == RcOperatingMode::AkwEncNone; } } // AudioVideoManagement