274 lines
8.9 KiB
C++
Executable File
274 lines
8.9 KiB
C++
Executable File
#include "cnr_frequency_planning_helper.h"
|
|
#include <AudioVideoManagement/avm_translation.h>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
#include <QSet>
|
|
#include <QVector>
|
|
// Todo: Better tr() ?
|
|
#include <QCoreApplication>
|
|
|
|
namespace AudioVideoManagement {
|
|
|
|
template<typename T>
|
|
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<ModulationType::inner_enum>(obj.value(QStringLiteral("ModulationType")).toInt(-1));
|
|
spec->channelSpacing = static_cast<ChannelSpacingHF::inner_enum>(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 <squelch < max
|
|
)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
QJsonObject RadioCircuitUHF::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"), squelchDB);
|
|
obj.insert(QStringLiteral("Clipper"), clipper);
|
|
obj.insert(QStringLiteral("AGC"), agc);
|
|
|
|
return obj;
|
|
}
|
|
|
|
RadioCircuitUHF* RadioCircuitUHF::fromJson(const QJsonObject &obj)
|
|
{
|
|
RadioCircuitUHF *spec = new RadioCircuitUHF();
|
|
spec->modulationType = static_cast<ModulationType::inner_enum>(obj.value(QStringLiteral("ModulationType")).toInt(-1));
|
|
spec->channelSpacing = static_cast<ChannelSpacing::inner_enum>(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<RcOperatingMode::inner_enum>(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<RadioCircuit*> fromJson(const std::string &json)
|
|
{
|
|
QVector<RadioCircuit*> 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<FrequencyBand::inner_enum>(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<int> frequencySetDataIds(const std::string &frequencyPlanDataProperties)
|
|
{
|
|
QSet<int> 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<FrequencyBand::inner_enum>(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
|