mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
VOR single channel: first working release of VOR localizer feature plugin
This commit is contained in:
parent
ffe515fb63
commit
6c02a78d62
@ -436,9 +436,17 @@ void VORDemodSC::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respon
|
||||
response.getVorDemodScReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
|
||||
response.getVorDemodScReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0);
|
||||
response.getVorDemodScReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate());
|
||||
response.getVorDemodScReport()->setNavId(m_settings.m_navId);
|
||||
response.getVorDemodScReport()->setRadial(m_radial);
|
||||
response.getVorDemodScReport()->setRefMag(m_refMag);
|
||||
response.getVorDemodScReport()->setVarMag(m_varMag);
|
||||
float refMagDB = std::round(20.0*std::log10(m_refMag));
|
||||
float varMagDB = std::round(20.0*std::log10(m_varMag));
|
||||
bool validRefMag = refMagDB > m_settings.m_refThresholdDB;
|
||||
bool validVarMag = varMagDB > m_settings.m_varThresholdDB;
|
||||
response.getVorDemodScReport()->setValidRadial(validRefMag && validVarMag ? 1 : 0);
|
||||
response.getVorDemodScReport()->setValidRefMag(validRefMag ? 1 : 0);
|
||||
response.getVorDemodScReport()->setValidVarMag(validVarMag ? 1 : 0);
|
||||
|
||||
if (response.getVorDemodScReport()->getMorseIdent()) {
|
||||
*response.getVorDemodScReport()->getMorseIdent() = m_morseIdent;
|
||||
@ -502,12 +510,15 @@ void VORDemodSC::featuresSendSettings(QList<QString>& channelSettingsKeys, const
|
||||
|
||||
void VORDemodSC::sendChannelReport(QList<MessageQueue*> *messageQueues)
|
||||
{
|
||||
SWGSDRangel::SWGChannelReport *swgChannelReport = new SWGSDRangel::SWGChannelReport();
|
||||
webapiFormatChannelReport(*swgChannelReport);
|
||||
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||
|
||||
for (; it != messageQueues->end(); ++it)
|
||||
{
|
||||
SWGSDRangel::SWGChannelReport *swgChannelReport = new SWGSDRangel::SWGChannelReport();
|
||||
swgChannelReport->setDirection(0);
|
||||
swgChannelReport->setChannelType(new QString(m_channelId));
|
||||
swgChannelReport->setVorDemodScReport(new SWGSDRangel::SWGVORDemodSCReport());
|
||||
webapiFormatChannelReport(*swgChannelReport);
|
||||
MainCore::MsgChannelReport *msg = MainCore::MsgChannelReport::create(this, swgChannelReport);
|
||||
(*it)->push(msg);
|
||||
}
|
||||
|
@ -303,6 +303,9 @@
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -367,6 +370,9 @@
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-40</number>
|
||||
</property>
|
||||
@ -416,6 +422,9 @@
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -655,7 +664,6 @@
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||
<include location="map.qrc"/>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
|
@ -302,7 +302,7 @@ void VORDemodSCSink::processOneSample(Complex &ci)
|
||||
{
|
||||
if (m_ident != "")
|
||||
{
|
||||
qDebug() << m_ident << " " << Morse::toString(m_ident);
|
||||
qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident);
|
||||
|
||||
if (getMessageQueueToChannel())
|
||||
{
|
||||
@ -343,7 +343,7 @@ void VORDemodSCSink::processOneSample(Complex &ci)
|
||||
m_ident = m_ident.simplified();
|
||||
if (m_ident != "")
|
||||
{
|
||||
qDebug() << m_ident << " " << Morse::toString(m_ident);
|
||||
qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident);
|
||||
|
||||
if (getMessageQueueToChannel())
|
||||
{
|
||||
|
@ -25,9 +25,16 @@
|
||||
#include "SWGFeatureActions.h"
|
||||
#include "SWGSimplePTTReport.h"
|
||||
#include "SWGDeviceState.h"
|
||||
#include "SWGChannelReport.h"
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspdevicesourceengine.h"
|
||||
#include "dsp/devicesamplesource.h"
|
||||
#include "device/deviceset.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "vorlocalizerreport.h"
|
||||
#include "vorlocalizerworker.h"
|
||||
#include "vorlocalizer.h"
|
||||
|
||||
@ -41,8 +48,7 @@ const char* const VORLocalizer::m_featureIdURI = "sdrangel.feature.vorlocalizer"
|
||||
const char* const VORLocalizer::m_featureId = "VORLocalizer";
|
||||
|
||||
VORLocalizer::VORLocalizer(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||
Feature(m_featureIdURI, webAPIAdapterInterface),
|
||||
m_ptt(false)
|
||||
Feature(m_featureIdURI, webAPIAdapterInterface)
|
||||
{
|
||||
setObjectName(m_featureId);
|
||||
m_worker = new VorLocalizerWorker(webAPIAdapterInterface);
|
||||
@ -64,7 +70,8 @@ void VORLocalizer::start()
|
||||
qDebug("VORLocalizer::start");
|
||||
|
||||
m_worker->reset();
|
||||
m_worker->setMessageQueueToGUI(getMessageQueueToGUI());
|
||||
m_worker->setMessageQueueToFeature(getInputMessageQueue());
|
||||
m_worker->setAvailableChannels(&m_availableChannels);
|
||||
bool ok = m_worker->startWork();
|
||||
m_state = ok ? StRunning : StError;
|
||||
m_thread.start();
|
||||
@ -108,11 +115,129 @@ bool VORLocalizer::handleMessage(const Message& cmd)
|
||||
else if (MsgRefreshChannels::match(cmd))
|
||||
{
|
||||
qDebug() << "VORLocalizer::handleMessage: MsgRefreshChannels";
|
||||
VorLocalizerWorker::MsgRefreshChannels *msg = VorLocalizerWorker::MsgRefreshChannels::create();
|
||||
m_worker->getInputMessageQueue()->push(msg);
|
||||
updateChannels();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else if (MainCore::MsgChannelReport::match(cmd))
|
||||
{
|
||||
MainCore::MsgChannelReport& report = (MainCore::MsgChannelReport&) cmd;
|
||||
SWGSDRangel::SWGChannelReport* swgChannelReport = report.getSWGReport();
|
||||
QString *channelType = swgChannelReport->getChannelType();
|
||||
|
||||
if (*channelType == "VORDemodSC")
|
||||
{
|
||||
SWGSDRangel::SWGVORDemodSCReport *swgVORDemodSCReport = swgChannelReport->getVorDemodScReport();
|
||||
int navId = swgVORDemodSCReport->getNavId();
|
||||
|
||||
if (navId < 0) { // disregard message for unallocated channels
|
||||
return true;
|
||||
}
|
||||
|
||||
bool singlePlan = (m_vorSinglePlans.contains(navId)) ? m_vorSinglePlans[navId] : false;
|
||||
|
||||
// qDebug() << "VORLocalizer::handleMessage: MainCore::MsgChannelReport(VORDemodSC): "
|
||||
// << "navId:" << navId
|
||||
// << "singlePlanProvided" << m_vorSinglePlans.contains(navId)
|
||||
// << "singlePlan:" << singlePlan;
|
||||
|
||||
if (m_vorChannelReports.contains(navId))
|
||||
{
|
||||
m_vorChannelReports[navId].m_radial = swgVORDemodSCReport->getRadial();
|
||||
m_vorChannelReports[navId].m_refMag = swgVORDemodSCReport->getRefMag();
|
||||
m_vorChannelReports[navId].m_varMag = swgVORDemodSCReport->getVarMag();
|
||||
m_vorChannelReports[navId].m_validRadial = swgVORDemodSCReport->getValidRadial() != 0;
|
||||
m_vorChannelReports[navId].m_validRefMag = swgVORDemodSCReport->getValidRefMag() != 0;
|
||||
m_vorChannelReports[navId].m_validVarMag = swgVORDemodSCReport->getValidVarMag() != 0;
|
||||
m_vorChannelReports[navId].m_morseIdent = *swgVORDemodSCReport->getMorseIdent();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vorChannelReports[navId] = VORChannelReport{
|
||||
swgVORDemodSCReport->getRadial(),
|
||||
swgVORDemodSCReport->getRefMag(),
|
||||
swgVORDemodSCReport->getVarMag(),
|
||||
AverageUtil<float, double>(),
|
||||
AverageUtil<float, double>(),
|
||||
AverageUtil<float, double>(),
|
||||
swgVORDemodSCReport->getValidRadial() != 0,
|
||||
swgVORDemodSCReport->getValidRefMag() != 0,
|
||||
swgVORDemodSCReport->getValidVarMag() != 0,
|
||||
*swgVORDemodSCReport->getMorseIdent()
|
||||
};
|
||||
}
|
||||
|
||||
if (m_vorChannelReports[navId].m_validRadial) {
|
||||
m_vorChannelReports[navId].m_radialAvg(swgVORDemodSCReport->getRadial());
|
||||
}
|
||||
if (m_vorChannelReports[navId].m_validRefMag) {
|
||||
m_vorChannelReports[navId].m_refMagAvg(swgVORDemodSCReport->getRefMag());
|
||||
}
|
||||
if (m_vorChannelReports[navId].m_validVarMag) {
|
||||
m_vorChannelReports[navId].m_varMagAvg(swgVORDemodSCReport->getVarMag());
|
||||
}
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
float radial = ((m_vorChannelReports[navId].m_radialAvg.getNumSamples() == 0) || singlePlan) ?
|
||||
m_vorChannelReports[navId].m_radial :
|
||||
m_vorChannelReports[navId].m_radialAvg.instantAverage();
|
||||
float refMag = ((m_vorChannelReports[navId].m_refMagAvg.getNumSamples() == 0) || singlePlan) ?
|
||||
m_vorChannelReports[navId].m_refMag :
|
||||
m_vorChannelReports[navId].m_refMagAvg.instantAverage();
|
||||
float varMag = ((m_vorChannelReports[navId].m_varMagAvg.getNumSamples() == 0) || singlePlan) ?
|
||||
m_vorChannelReports[navId].m_varMag :
|
||||
m_vorChannelReports[navId].m_varMagAvg.instantAverage();
|
||||
bool validRadial = singlePlan ? m_vorChannelReports[navId].m_validRadial :
|
||||
m_vorChannelReports[navId].m_radialAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validRadial;
|
||||
bool validRefMag = singlePlan ? m_vorChannelReports[navId].m_validRefMag :
|
||||
m_vorChannelReports[navId].m_refMagAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validRefMag;
|
||||
bool validVarMag = singlePlan ? m_vorChannelReports[navId].m_validVarMag :
|
||||
m_vorChannelReports[navId].m_varMagAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validVarMag;
|
||||
VORLocalizerReport::MsgReportRadial *msgRadial = VORLocalizerReport::MsgReportRadial::create(
|
||||
navId,
|
||||
radial,
|
||||
refMag,
|
||||
varMag,
|
||||
validRadial,
|
||||
validRefMag,
|
||||
validVarMag
|
||||
);
|
||||
getMessageQueueToGUI()->push(msgRadial);
|
||||
VORLocalizerReport::MsgReportIdent *msgIdent = VORLocalizerReport::MsgReportIdent::create(
|
||||
navId,
|
||||
m_vorChannelReports[navId].m_morseIdent
|
||||
);
|
||||
getMessageQueueToGUI()->push(msgIdent);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (VORLocalizerReport::MsgReportServiceddVORs::match(cmd))
|
||||
{
|
||||
qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs:";
|
||||
VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) cmd;
|
||||
std::vector<int>& vorNavIds = report.getNavIds();
|
||||
m_vorSinglePlans = report.getSinglePlans();
|
||||
|
||||
for (std::vector<int>::const_iterator it = vorNavIds.begin(); it != vorNavIds.end(); ++it)
|
||||
{
|
||||
m_vorChannelReports[*it].m_radialAvg.reset();
|
||||
m_vorChannelReports[*it].m_refMagAvg.reset();
|
||||
m_vorChannelReports[*it].m_varMagAvg.reset();
|
||||
}
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
VORLocalizerReport::MsgReportServiceddVORs *msgToGUI = VORLocalizerReport::MsgReportServiceddVORs::create();
|
||||
msgToGUI->getNavIds() = vorNavIds;
|
||||
getMessageQueueToGUI()->push(msgToGUI);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -146,6 +271,8 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
||||
<< " m_title: " << settings.m_title
|
||||
<< " m_rgbColor: " << settings.m_rgbColor
|
||||
<< " m_magDecAdjust: " << settings.m_magDecAdjust
|
||||
<< " m_rrTime: " << settings.m_rrTime
|
||||
<< " m_centerShift: " << settings.m_centerShift
|
||||
<< " force: " << force;
|
||||
|
||||
QList<QString> reverseAPIKeys;
|
||||
@ -159,6 +286,12 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
||||
if ((m_settings.m_magDecAdjust != settings.m_magDecAdjust) || force) {
|
||||
reverseAPIKeys.append("magDecAdjust");
|
||||
}
|
||||
if ((m_settings.m_rrTime != settings.m_rrTime) || force) {
|
||||
reverseAPIKeys.append("rrTime");
|
||||
}
|
||||
if ((m_settings.m_centerShift != settings.m_centerShift) || force) {
|
||||
reverseAPIKeys.append("centerShift");
|
||||
}
|
||||
|
||||
VorLocalizerWorker::MsgConfigureVORLocalizerWorker *msg = VorLocalizerWorker::MsgConfigureVORLocalizerWorker::create(
|
||||
settings, force
|
||||
@ -178,6 +311,75 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
void VORLocalizer::updateChannels()
|
||||
{
|
||||
MainCore *mainCore = MainCore::instance();
|
||||
MessagePipes& messagePipes = mainCore->getMessagePipes();
|
||||
std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets();
|
||||
std::vector<DeviceSet*>::const_iterator it = deviceSets.begin();
|
||||
m_availableChannels.clear();
|
||||
|
||||
int deviceIndex = 0;
|
||||
|
||||
for (; it != deviceSets.end(); ++it, deviceIndex++)
|
||||
{
|
||||
DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine;
|
||||
|
||||
if (deviceSourceEngine)
|
||||
{
|
||||
DeviceSampleSource *deviceSource = deviceSourceEngine->getSource();
|
||||
quint64 deviceCenterFrequency = deviceSource->getCenterFrequency();
|
||||
int basebandSampleRate = deviceSource->getSampleRate();
|
||||
|
||||
for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++)
|
||||
{
|
||||
ChannelAPI *channel = (*it)->getChannelAt(chi);
|
||||
|
||||
if (channel->getURI() == "sdrangel.channel.vordemodsc")
|
||||
{
|
||||
if (!m_availableChannels.contains(channel))
|
||||
{
|
||||
MessageQueue *messageQueue = messagePipes.registerChannelToFeature(channel, this, "report");
|
||||
QObject::connect(
|
||||
messageQueue,
|
||||
&MessageQueue::messageEnqueued,
|
||||
this,
|
||||
[=](){ this->handleChannelMessageQueue(messageQueue); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
}
|
||||
|
||||
VORLocalizerSettings::AvailableChannel availableChannel =
|
||||
VORLocalizerSettings::AvailableChannel{deviceIndex, chi, channel, deviceCenterFrequency, basebandSampleRate, -1};
|
||||
m_availableChannels[channel] = availableChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
VORLocalizerReport::MsgReportChannels *msgToGUI = VORLocalizerReport::MsgReportChannels::create();
|
||||
std::vector<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msgToGUI->getChannels();
|
||||
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::iterator it = m_availableChannels.begin();
|
||||
|
||||
for (; it != m_availableChannels.end(); ++it)
|
||||
{
|
||||
VORLocalizerReport::MsgReportChannels::Channel msgChannel =
|
||||
VORLocalizerReport::MsgReportChannels::Channel{
|
||||
it->m_deviceSetIndex,
|
||||
it->m_channelIndex
|
||||
};
|
||||
msgChannels.push_back(msgChannel);
|
||||
}
|
||||
|
||||
getMessageQueueToGUI()->push(msgToGUI);
|
||||
}
|
||||
|
||||
VorLocalizerWorker::MsgRefreshChannels *msgToWorker = VorLocalizerWorker::MsgRefreshChannels::create();
|
||||
m_worker->getInputMessageQueue()->push(msgToWorker);
|
||||
}
|
||||
|
||||
int VORLocalizer::webapiRun(bool run,
|
||||
SWGSDRangel::SWGDeviceState& response,
|
||||
QString& errorMessage)
|
||||
@ -237,6 +439,8 @@ void VORLocalizer::webapiFormatFeatureSettings(
|
||||
|
||||
response.getVorLocalizerSettings()->setRgbColor(settings.m_rgbColor);
|
||||
response.getVorLocalizerSettings()->setMagDecAdjust(settings.m_magDecAdjust);
|
||||
response.getVorLocalizerSettings()->setRrTime(settings.m_rrTime);
|
||||
response.getVorLocalizerSettings()->setCenterShift(settings.m_centerShift);
|
||||
|
||||
response.getVorLocalizerSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
||||
|
||||
@ -265,6 +469,12 @@ void VORLocalizer::webapiUpdateFeatureSettings(
|
||||
if (featureSettingsKeys.contains("magDecAdjust")) {
|
||||
settings.m_magDecAdjust = response.getVorLocalizerSettings()->getMagDecAdjust();
|
||||
}
|
||||
if (featureSettingsKeys.contains("rrTime")) {
|
||||
settings.m_rrTime = response.getVorLocalizerSettings()->getRrTime();
|
||||
}
|
||||
if (featureSettingsKeys.contains("centerShift")) {
|
||||
settings.m_centerShift = response.getVorLocalizerSettings()->getCenterShift();
|
||||
}
|
||||
if (featureSettingsKeys.contains("useReverseAPI")) {
|
||||
settings.m_useReverseAPI = response.getVorLocalizerSettings()->getUseReverseApi() != 0;
|
||||
}
|
||||
@ -302,6 +512,12 @@ void VORLocalizer::webapiReverseSendSettings(QList<QString>& channelSettingsKeys
|
||||
if (channelSettingsKeys.contains("magDecAdjust") || force) {
|
||||
swgVORLocalizerSettings->setMagDecAdjust(settings.m_magDecAdjust);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rrTime") || force) {
|
||||
swgVORLocalizerSettings->setRrTime(settings.m_rrTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("centerShift") || force) {
|
||||
swgVORLocalizerSettings->setCenterShift(settings.m_centerShift);
|
||||
}
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
|
||||
.arg(settings.m_reverseAPIAddress)
|
||||
@ -343,3 +559,15 @@ void VORLocalizer::networkManagerFinished(QNetworkReply *reply)
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void VORLocalizer::handleChannelMessageQueue(MessageQueue* messageQueue)
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = messageQueue->pop()) != nullptr)
|
||||
{
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "feature/feature.h"
|
||||
#include "util/message.h"
|
||||
#include "util/average.h"
|
||||
|
||||
#include "vorlocalizersettings.h"
|
||||
|
||||
@ -170,10 +171,30 @@ public:
|
||||
static const char* const m_featureId;
|
||||
|
||||
private:
|
||||
struct VORChannelReport
|
||||
{
|
||||
float m_radial; //!< current detected radial
|
||||
float m_refMag; //!< current reference signal magnitude
|
||||
float m_varMag; //!< current variable signal magnitude
|
||||
AverageUtil<float, double> m_radialAvg;
|
||||
AverageUtil<float, double> m_refMagAvg;
|
||||
AverageUtil<float, double> m_varMagAvg;
|
||||
bool m_validRadial;
|
||||
bool m_validRefMag;
|
||||
bool m_validVarMag;
|
||||
QString m_morseIdent; //!< identification morse code transcript
|
||||
|
||||
VORChannelReport() = default;
|
||||
VORChannelReport(const VORChannelReport&) = default;
|
||||
VORChannelReport& operator=(const VORChannelReport&) = default;
|
||||
};
|
||||
|
||||
QThread m_thread;
|
||||
VorLocalizerWorker *m_worker;
|
||||
VORLocalizerSettings m_settings;
|
||||
bool m_ptt;
|
||||
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> m_availableChannels;
|
||||
QHash<int, VORChannelReport> m_vorChannelReports;
|
||||
QHash<int, bool> m_vorSinglePlans;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
@ -181,10 +202,13 @@ private:
|
||||
void start();
|
||||
void stop();
|
||||
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
||||
void updateChannels();
|
||||
void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const VORLocalizerSettings& settings, bool force);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void handleChannelMessageQueue(MessageQueue* messageQueue);
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_VORLOCALIZER_H_
|
||||
|
@ -333,8 +333,10 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
||||
double cosLat1 = cos(lat1Rad);
|
||||
double cosLat2 = cos(lat2Rad);
|
||||
double delta12 = 2.0 * asin(sqrt(sindlat*sindlat+cosLat1*cosLat2*sindlon*sindlon));
|
||||
if (abs(delta12) < std::numeric_limits<float>::epsilon())
|
||||
|
||||
if (abs(delta12) < std::numeric_limits<float>::epsilon()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double sinLat1 = sin(lat1Rad);
|
||||
double sinLat2 = sin(lat2Rad);
|
||||
@ -342,8 +344,8 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
||||
double cosDelta12 = cos(delta12);
|
||||
double thetaA = acos((sinLat2-sinLat1*cosDelta12)/(sinDelta12*cosLat1));
|
||||
double thetaB = acos((sinLat1-sinLat2*cosDelta12)/(sinDelta12*cosLat2));
|
||||
|
||||
double theta12, theta21;
|
||||
|
||||
if (sin(lon2Rad-lon1Rad) > 0.0)
|
||||
{
|
||||
theta12 = thetaA;
|
||||
@ -354,14 +356,19 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
||||
theta12 = 2.0*M_PI-thetaA;
|
||||
theta21 = thetaB;
|
||||
}
|
||||
|
||||
double alpha1 = theta13 - theta12;
|
||||
double alpha2 = theta21 - theta23;
|
||||
double sinAlpha1 = sin(alpha1);
|
||||
double sinAlpha2 = sin(alpha2);
|
||||
if ((sinAlpha1 == 0.0) && (sinAlpha2 == 0.0))
|
||||
|
||||
if ((sinAlpha1 == 0.0) && (sinAlpha2 == 0.0)) {
|
||||
return false;
|
||||
if (sinAlpha1*sinAlpha2 < 0.0)
|
||||
}
|
||||
if (sinAlpha1*sinAlpha2 < 0.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double cosAlpha1 = cos(alpha1);
|
||||
double cosAlpha2 = cos(alpha2);
|
||||
double cosAlpha3 = -cosAlpha1*cosAlpha2+sinAlpha1*sinAlpha2*cos(delta12);
|
||||
@ -382,7 +389,7 @@ VORGUI::VORGUI(NavAid *navAid, VORLocalizerGUI *gui) :
|
||||
// These are deleted by QTableWidget
|
||||
m_nameItem = new QTableWidgetItem();
|
||||
m_frequencyItem = new QTableWidgetItem();
|
||||
m_offsetItem = new QTableWidgetItem();
|
||||
m_navIdItem = new QTableWidgetItem();
|
||||
m_radialItem = new QTableWidgetItem();
|
||||
m_identItem = new QTableWidgetItem();
|
||||
m_morseItem = new QTableWidgetItem();
|
||||
@ -412,15 +419,18 @@ VORGUI::VORGUI(NavAid *navAid, VORLocalizerGUI *gui) :
|
||||
|
||||
void VORGUI::on_audioMute_toggled(bool checked)
|
||||
{
|
||||
m_gui->m_settings.m_subChannelSettings.value(m_navAid->m_id)->m_audioMute = checked;
|
||||
m_gui->m_settings.m_subChannelSettings[m_navAid->m_id].m_audioMute = checked;
|
||||
m_gui->applySettings();
|
||||
}
|
||||
|
||||
QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int row = index.row();
|
||||
if ((row < 0) || (row >= m_vors.count()))
|
||||
|
||||
if ((row < 0) || (row >= m_vors.count())) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == VORModel::positionRole)
|
||||
{
|
||||
// Coordinates to display the VOR icon at
|
||||
@ -436,15 +446,22 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||
QStringList list;
|
||||
list.append(QString("Name: %1").arg(m_vors[row]->m_name));
|
||||
list.append(QString("Frequency: %1 MHz").arg(m_vors[row]->m_frequencykHz / 1000.0f, 0, 'f', 1));
|
||||
if (m_vors[row]->m_channel != "")
|
||||
|
||||
if (m_vors[row]->m_channel != "") {
|
||||
list.append(QString("Channel: %1").arg(m_vors[row]->m_channel));
|
||||
}
|
||||
|
||||
list.append(QString("Ident: %1 %2").arg(m_vors[row]->m_ident).arg(Morse::toSpacedUnicodeMorse(m_vors[row]->m_ident)));
|
||||
list.append(QString("Range: %1 nm").arg(m_vors[row]->m_range));
|
||||
if (m_vors[row]->m_alignedTrueNorth)
|
||||
|
||||
if (m_vors[row]->m_alignedTrueNorth) {
|
||||
list.append(QString("Magnetic declination: Aligned to true North"));
|
||||
else if (m_vors[row]->m_magneticDeclination != 0.0f)
|
||||
} else if (m_vors[row]->m_magneticDeclination != 0.0f) {
|
||||
list.append(QString("Magnetic declination: %1%2").arg(std::round(m_vors[row]->m_magneticDeclination)).arg(QChar(0x00b0)));
|
||||
}
|
||||
|
||||
QString data = list.join("\n");
|
||||
|
||||
return QVariant::fromValue(data);
|
||||
}
|
||||
else if (role == VORModel::vorImageRole)
|
||||
@ -455,10 +472,11 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||
else if (role == VORModel::bubbleColourRole)
|
||||
{
|
||||
// Select a background colour for the text bubble next to the VOR
|
||||
if (m_selected[row])
|
||||
if (m_selected[row]) {
|
||||
return QVariant::fromValue(QColor("lightgreen"));
|
||||
else
|
||||
} else {
|
||||
return QVariant::fromValue(QColor("lightblue"));
|
||||
}
|
||||
}
|
||||
else if (role == VORModel::vorRadialRole)
|
||||
{
|
||||
@ -471,10 +489,13 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
float endLat, endLong;
|
||||
float bearing;
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[row]->m_alignedTrueNorth)
|
||||
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[row]->m_alignedTrueNorth) {
|
||||
bearing = m_radials[row] - m_vors[row]->m_magneticDeclination;
|
||||
else
|
||||
} else {
|
||||
bearing = m_radials[row];
|
||||
}
|
||||
|
||||
calcRadialEndPoint(m_vors[row]->m_latitude, m_vors[row]->m_longitude, m_vors[row]->getRangeMetres(), bearing, endLat, endLong);
|
||||
list.push_back(QVariant::fromValue(*new QGeoCoordinate(endLat, endLong, Units::feetToMetres(m_vors[row]->m_elevation))));
|
||||
|
||||
@ -484,36 +505,49 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||
return QVariantList();
|
||||
}
|
||||
else if (role == VORModel::selectedRole)
|
||||
{
|
||||
return QVariant::fromValue(m_selected[row]);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool VORModel::setData(const QModelIndex &index, const QVariant& value, int role)
|
||||
{
|
||||
int row = index.row();
|
||||
if ((row < 0) || (row >= m_vors.count()))
|
||||
|
||||
if ((row < 0) || (row >= m_vors.count())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (role == VORModel::selectedRole)
|
||||
{
|
||||
bool selected = value.toBool();
|
||||
VORGUI *vorGUI;
|
||||
if (selected == true)
|
||||
|
||||
if (selected)
|
||||
{
|
||||
vorGUI = new VORGUI(m_vors[row], m_gui);
|
||||
m_vorGUIs[row] = vorGUI;
|
||||
}
|
||||
else
|
||||
{
|
||||
vorGUI = m_vorGUIs[row];
|
||||
}
|
||||
|
||||
m_gui->selectVOR(vorGUI, selected);
|
||||
m_selected[row] = selected;
|
||||
emit dataChanged(index, index);
|
||||
|
||||
if (!selected)
|
||||
{
|
||||
delete vorGUI;
|
||||
m_vorGUIs[row] = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -533,28 +567,33 @@ bool VORModel::findIntersection(float &lat, float &lon)
|
||||
{
|
||||
lat1 = m_vors[i]->m_latitude;
|
||||
lon1 = m_vors[i]->m_longitude;
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth)
|
||||
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth) {
|
||||
bearing1 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
||||
else
|
||||
} else {
|
||||
bearing1 = m_radials[i];
|
||||
}
|
||||
|
||||
valid1 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lat2 = m_vors[i]->m_latitude;
|
||||
lon2 = m_vors[i]->m_longitude;
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth)
|
||||
|
||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth) {
|
||||
bearing2 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
||||
else
|
||||
} else {
|
||||
bearing2 = m_radials[i];
|
||||
}
|
||||
|
||||
valid2 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid1 && valid2)
|
||||
{
|
||||
if (valid1 && valid2) {
|
||||
return calcIntersectionPoint(lat1, lon1, bearing1, lat2, lon2, bearing2, lat, lon);
|
||||
}
|
||||
}
|
||||
@ -571,7 +610,7 @@ void VORLocalizerGUI::resizeTable()
|
||||
ui->vorData->setRowCount(row + 1);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, new QTableWidgetItem("White Sulphur Springs"));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, new QTableWidgetItem("Freq (MHz) "));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_OFFSET, new QTableWidgetItem("Offset (kHz) "));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAVID, new QTableWidgetItem("99999999"));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, new QTableWidgetItem("Ident "));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, new QTableWidgetItem(Morse::toSpacedUnicode(morse)));
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, new QTableWidgetItem("Radial (o) "));
|
||||
@ -588,7 +627,6 @@ void VORLocalizerGUI::resizeTable()
|
||||
void VORLocalizerGUI::vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
|
||||
{
|
||||
(void) oldVisualIndex;
|
||||
|
||||
m_settings.m_columnIndexes[logicalIndex] = newVisualIndex;
|
||||
}
|
||||
|
||||
@ -596,7 +634,6 @@ void VORLocalizerGUI::vorData_sectionMoved(int logicalIndex, int oldVisualIndex,
|
||||
void VORLocalizerGUI::vorData_sectionResized(int logicalIndex, int oldSize, int newSize)
|
||||
{
|
||||
(void) oldSize;
|
||||
|
||||
m_settings.m_columnSizes[logicalIndex] = newSize;
|
||||
}
|
||||
|
||||
@ -610,9 +647,9 @@ void VORLocalizerGUI::columnSelectMenu(QPoint pos)
|
||||
void VORLocalizerGUI::columnSelectMenuChecked(bool checked)
|
||||
{
|
||||
(void) checked;
|
||||
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
if (action != nullptr)
|
||||
|
||||
if (action)
|
||||
{
|
||||
int idx = action->data().toInt(nullptr);
|
||||
ui->vorData->setColumnHidden(idx, !action->isChecked());
|
||||
@ -627,6 +664,7 @@ QAction *VORLocalizerGUI::createCheckableItem(QString &text, int idx, bool check
|
||||
action->setChecked(checked);
|
||||
action->setData(QVariant(idx));
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(columnSelectMenuChecked()));
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
@ -646,7 +684,7 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
||||
ui->vorData->setRowCount(row + 1);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, vorGUI->m_nameItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, vorGUI->m_frequencyItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_OFFSET, vorGUI->m_offsetItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAVID, vorGUI->m_navIdItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, vorGUI->m_identItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, vorGUI->m_morseItem);
|
||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, vorGUI->m_radialItem);
|
||||
@ -662,11 +700,11 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
||||
ui->vorData->setSortingEnabled(true);
|
||||
|
||||
// Add to settings to create corresponding demodulator
|
||||
VORLocalizerSubChannelSettings *subChannelSettings = new VORLocalizerSubChannelSettings();
|
||||
subChannelSettings->m_id = navId;
|
||||
subChannelSettings->m_frequency = vorGUI->m_navAid->m_frequencykHz * 1000;
|
||||
subChannelSettings->m_audioMute = false;
|
||||
m_settings.m_subChannelSettings.insert(navId, subChannelSettings);
|
||||
m_settings.m_subChannelSettings.insert(navId, VORLocalizerSubChannelSettings{
|
||||
navId,
|
||||
vorGUI->m_navAid->m_frequencykHz * 1000,
|
||||
false
|
||||
});
|
||||
|
||||
applySettings();
|
||||
}
|
||||
@ -678,9 +716,7 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
||||
m_selectedVORs.remove(navId);
|
||||
ui->vorData->removeRow(vorGUI->m_nameItem->row());
|
||||
// Remove from settings to remove corresponding demodulator
|
||||
VORLocalizerSubChannelSettings *subChannelSettings = m_settings.m_subChannelSettings.value(navId);
|
||||
m_settings.m_subChannelSettings.remove(navId);
|
||||
delete subChannelSettings;
|
||||
|
||||
applySettings();
|
||||
}
|
||||
@ -701,10 +737,10 @@ void VORLocalizerGUI::updateVORs()
|
||||
azEl.calculate();
|
||||
|
||||
// Only display VOR if in range
|
||||
if (azEl.getDistance() <= 200000)
|
||||
{
|
||||
if (azEl.getDistance() <= 200000) {
|
||||
m_vorModel.addVOR(vor);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@ -734,11 +770,14 @@ QByteArray VORLocalizerGUI::serialize() const
|
||||
|
||||
bool VORLocalizerGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data)) {
|
||||
if (m_settings.deserialize(data))
|
||||
{
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
@ -775,50 +814,36 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
||||
Real refMagDB = std::round(20.0*std::log10(report.getRefMag()));
|
||||
|
||||
bool validRadial = report.getValidRadial();
|
||||
|
||||
vorGUI->m_radialItem->setData(Qt::DisplayRole, std::round(report.getRadial()));
|
||||
if (validRadial)
|
||||
vorGUI->m_navIdItem->setData(Qt::DisplayRole, subChannelId);
|
||||
|
||||
if (validRadial) {
|
||||
vorGUI->m_radialItem->setForeground(QBrush(Qt::white));
|
||||
else
|
||||
} else {
|
||||
vorGUI->m_radialItem->setForeground(QBrush(Qt::red));
|
||||
}
|
||||
|
||||
vorGUI->m_refMagItem->setData(Qt::DisplayRole, refMagDB);
|
||||
if (report.getValidRefMag())
|
||||
|
||||
if (report.getValidRefMag()) {
|
||||
vorGUI->m_refMagItem->setForeground(QBrush(Qt::white));
|
||||
else
|
||||
} else {
|
||||
vorGUI->m_refMagItem->setForeground(QBrush(Qt::red));
|
||||
}
|
||||
|
||||
vorGUI->m_varMagItem->setData(Qt::DisplayRole, varMagDB);
|
||||
if (report.getValidVarMag())
|
||||
|
||||
if (report.getValidVarMag()) {
|
||||
vorGUI->m_varMagItem->setForeground(QBrush(Qt::white));
|
||||
else
|
||||
} else {
|
||||
vorGUI->m_varMagItem->setForeground(QBrush(Qt::red));
|
||||
}
|
||||
|
||||
// Update radial on map
|
||||
m_vorModel.setRadial(subChannelId, validRadial, report.getRadial());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (VORLocalizerReport::MsgReportFreqOffset::match(message))
|
||||
{
|
||||
VORLocalizerReport::MsgReportFreqOffset& report = (VORLocalizerReport::MsgReportFreqOffset&) message;
|
||||
int subChannelId = report.getSubChannelId();
|
||||
|
||||
VORGUI *vorGUI = m_selectedVORs.value(subChannelId);
|
||||
|
||||
vorGUI->m_offsetItem->setData(Qt::DisplayRole, report.getFreqOffset() / 1000.0);
|
||||
if (report.getOutOfBand())
|
||||
{
|
||||
vorGUI->m_offsetItem->setForeground(QBrush(Qt::red));
|
||||
// Clear other fields as data is now invalid
|
||||
vorGUI->m_radialItem->setText("");
|
||||
vorGUI->m_refMagItem->setText("");
|
||||
vorGUI->m_varMagItem->setText("");
|
||||
m_vorModel.setRadial(subChannelId, false, -1.0f);
|
||||
}
|
||||
else
|
||||
vorGUI->m_offsetItem->setForeground(QBrush(Qt::white));
|
||||
}
|
||||
else if (VORLocalizerReport::MsgReportIdent::match(message))
|
||||
{
|
||||
VORLocalizerReport::MsgReportIdent& report = (VORLocalizerReport::MsgReportIdent&) message;
|
||||
@ -835,6 +860,7 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
||||
{
|
||||
vorGUI->m_rxIdentItem->setText(identString);
|
||||
vorGUI->m_rxMorseItem->setText(Morse::toSpacedUnicode(ident));
|
||||
|
||||
if (vorGUI->m_navAid->m_ident == identString)
|
||||
{
|
||||
// Set colour to green if matching expected ident
|
||||
@ -868,11 +894,29 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
||||
ui->channels->clear();
|
||||
|
||||
for (; it != channels.end(); ++it) {
|
||||
ui->channels->addItem(tr("%1:%2").arg(it->m_deviceSetIndex).arg(it->m_channelIndex));
|
||||
ui->channels->addItem(tr("R%1:%2").arg(it->m_deviceSetIndex).arg(it->m_channelIndex));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (VORLocalizerReport::MsgReportServiceddVORs::match(message))
|
||||
{
|
||||
VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) message;
|
||||
std::vector<int>& servicedVORNavIds = report.getNavIds();
|
||||
|
||||
for (auto vorGUI : m_selectedVORs) {
|
||||
vorGUI->m_frequencyItem->setForeground(QBrush(Qt::white));
|
||||
}
|
||||
|
||||
for (auto navId : servicedVORNavIds)
|
||||
{
|
||||
if (m_selectedVORs.contains(navId))
|
||||
{
|
||||
VORGUI *vorGUI = m_selectedVORs[navId];
|
||||
vorGUI->m_frequencyItem->setForeground(QBrush(Qt::green));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -883,8 +927,7 @@ void VORLocalizerGUI::handleInputMessages()
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
@ -893,31 +936,41 @@ void VORLocalizerGUI::handleInputMessages()
|
||||
qint64 VORLocalizerGUI::fileAgeInDays(QString filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
QDateTime modified = file.fileTime(QFileDevice::FileModificationTime);
|
||||
if (modified.isValid())
|
||||
|
||||
if (modified.isValid()) {
|
||||
return modified.daysTo(QDateTime::currentDateTime());
|
||||
else
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool VORLocalizerGUI::confirmDownload(QString filename)
|
||||
{
|
||||
qint64 age = fileAgeInDays(filename);
|
||||
|
||||
if ((age == -1) || (age > 100))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::StandardButton reply;
|
||||
if (age == 0)
|
||||
|
||||
if (age == 0) {
|
||||
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded today. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
||||
else if (age == 1)
|
||||
} else if (age == 1) {
|
||||
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded yesterday. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
||||
else
|
||||
} else {
|
||||
reply = QMessageBox::question(this, "Confirm download", QString("This file was last downloaded %1 days ago. Are you sure you wish to redownload this file?").arg(age), QMessageBox::Yes|QMessageBox::No);
|
||||
}
|
||||
|
||||
return reply == QMessageBox::Yes;
|
||||
}
|
||||
}
|
||||
@ -932,18 +985,20 @@ QString VORLocalizerGUI::getDataDir()
|
||||
|
||||
QString VORLocalizerGUI::getOpenAIPVORDBFilename(int i)
|
||||
{
|
||||
if (countryCodes[i] != nullptr)
|
||||
if (countryCodes[i] != nullptr) {
|
||||
return getDataDir() + "/" + countryCodes[i] + "_nav.aip";
|
||||
else
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QString VORLocalizerGUI::getOpenAIPVORDBURL(int i)
|
||||
{
|
||||
if (countryCodes[i] != nullptr)
|
||||
if (countryCodes[i] != nullptr) {
|
||||
return QString(OPENAIP_NAVAIDS_URL).arg(countryCodes[i]);
|
||||
else
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QString VORLocalizerGUI::getVORDBFilename()
|
||||
@ -964,14 +1019,18 @@ void VORLocalizerGUI::downloadFinished(const QString& filename, bool success)
|
||||
if (filename == getVORDBFilename())
|
||||
{
|
||||
m_vors = NavAid::readNavAidsDB(filename);
|
||||
if (m_vors != nullptr)
|
||||
|
||||
if (m_vors != nullptr) {
|
||||
updateVORs();
|
||||
}
|
||||
|
||||
m_progressDialog->close();
|
||||
m_progressDialog = nullptr;
|
||||
}
|
||||
else if (filename == getOpenAIPVORDBFilename(m_countryIndex))
|
||||
{
|
||||
m_countryIndex++;
|
||||
|
||||
if (countryCodes[m_countryIndex] != nullptr)
|
||||
{
|
||||
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
||||
@ -984,8 +1043,11 @@ void VORLocalizerGUI::downloadFinished(const QString& filename, bool success)
|
||||
else
|
||||
{
|
||||
readNavAids();
|
||||
if (m_vors != nullptr)
|
||||
|
||||
if (m_vors) {
|
||||
updateVORs();
|
||||
}
|
||||
|
||||
m_progressDialog->close();
|
||||
m_progressDialog = nullptr;
|
||||
}
|
||||
@ -1021,6 +1083,7 @@ void VORLocalizerGUI::on_getOurAirportsVORDB_clicked()
|
||||
if (m_progressDialog == nullptr)
|
||||
{
|
||||
QString vorDBFile = getVORDBFilename();
|
||||
|
||||
if (confirmDownload(vorDBFile))
|
||||
{
|
||||
// Download OurAirports navaid database to disk
|
||||
@ -1039,10 +1102,11 @@ void VORLocalizerGUI::on_getOurAirportsVORDB_clicked()
|
||||
void VORLocalizerGUI::on_getOpenAIPVORDB_clicked()
|
||||
{
|
||||
// Don't try to download while already in progress
|
||||
if (m_progressDialog == nullptr)
|
||||
if (!m_progressDialog)
|
||||
{
|
||||
m_countryIndex = 0;
|
||||
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
||||
|
||||
if (confirmDownload(vorDBFile))
|
||||
{
|
||||
// Download OpenAIP XML to disk
|
||||
@ -1071,13 +1135,27 @@ void VORLocalizerGUI::readNavAids()
|
||||
}
|
||||
}
|
||||
|
||||
void VORLocalizerGUI::on_magDecAdjust_clicked(bool checked)
|
||||
void VORLocalizerGUI::on_magDecAdjust_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_magDecAdjust = checked;
|
||||
m_vorModel.allVORUpdated();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void VORLocalizerGUI::on_rrTime_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_rrTime = value;
|
||||
ui->rrTimeText->setText(tr("%1s").arg(m_settings.m_rrTime));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void VORLocalizerGUI::on_centerShift_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_centerShift = value * 1000;
|
||||
ui->centerShiftText->setText(tr("%1k").arg(value));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void VORLocalizerGUI::on_channelsRefresh_clicked()
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
@ -1170,6 +1248,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||
// Centre map at My Position
|
||||
QQuickItem *item = ui->map->rootObject();
|
||||
QObject *object = item->findChild<QObject*>("map");
|
||||
|
||||
if (object)
|
||||
{
|
||||
QGeoCoordinate coords = object->property("center").value<QGeoCoordinate>();
|
||||
@ -1177,8 +1256,10 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||
coords.setLongitude(stationLongitude);
|
||||
object->setProperty("center", QVariant::fromValue(coords));
|
||||
}
|
||||
|
||||
// Move antenna icon to My Position to start with
|
||||
QObject *stationObject = item->findChild<QObject*>("station");
|
||||
|
||||
if (stationObject)
|
||||
{
|
||||
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
||||
@ -1191,6 +1272,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||
|
||||
// Read in VOR information if it exists
|
||||
bool useOurAirports = false;
|
||||
|
||||
if (useOurAirports)
|
||||
{
|
||||
m_vors = NavAid::readNavAidsDB(getVORDBFilename());
|
||||
@ -1201,7 +1283,8 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||
readNavAids();
|
||||
ui->getOurAirportsVORDB->setVisible(false);
|
||||
}
|
||||
if (m_vors != nullptr) {
|
||||
|
||||
if (m_vors) {
|
||||
updateVORs();
|
||||
}
|
||||
|
||||
@ -1213,11 +1296,13 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
||||
ui->vorData->setSortingEnabled(true);
|
||||
// Add context menu to allow hiding/showing of columns
|
||||
menu = new QMenu(ui->vorData);
|
||||
|
||||
for (int i = 0; i < ui->vorData->horizontalHeader()->count(); i++)
|
||||
{
|
||||
QString text = ui->vorData->horizontalHeaderItem(i)->text();
|
||||
menu->addAction(createCheckableItem(text, i, true));
|
||||
}
|
||||
|
||||
ui->vorData->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->vorData->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(columnSelectMenu(QPoint)));
|
||||
// Get signals when columns change
|
||||
@ -1273,6 +1358,11 @@ void VORLocalizerGUI::displaySettings()
|
||||
header->moveSection(header->visualIndex(i), m_settings.m_columnIndexes[i]);
|
||||
}
|
||||
|
||||
ui->rrTimeText->setText(tr("%1s").arg(m_settings.m_rrTime));
|
||||
ui->rrTime->setValue(m_settings.m_rrTime);
|
||||
ui->centerShiftText->setText(tr("%1k").arg(m_settings.m_centerShift/1000));
|
||||
ui->centerShift->setValue(m_settings.m_centerShift/1000);
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -1325,6 +1415,7 @@ void VORLocalizerGUI::tick()
|
||||
// Move antenna icon to estimated position
|
||||
QQuickItem *item = ui->map->rootObject();
|
||||
QObject *stationObject = item->findChild<QObject*>("station");
|
||||
|
||||
if(stationObject != NULL)
|
||||
{
|
||||
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
|
||||
QTableWidgetItem *m_nameItem;
|
||||
QTableWidgetItem *m_frequencyItem;
|
||||
QTableWidgetItem *m_offsetItem;
|
||||
QTableWidgetItem *m_navIdItem;
|
||||
QTableWidgetItem *m_identItem;
|
||||
QTableWidgetItem *m_morseItem;
|
||||
QTableWidgetItem *m_radialItem;
|
||||
@ -269,7 +269,9 @@ private slots:
|
||||
void on_startStop_toggled(bool checked);
|
||||
void on_getOurAirportsVORDB_clicked();
|
||||
void on_getOpenAIPVORDB_clicked();
|
||||
void on_magDecAdjust_clicked(bool checked);
|
||||
void on_magDecAdjust_toggled(bool checked);
|
||||
void on_rrTime_valueChanged(int value);
|
||||
void on_centerShift_valueChanged(int value);
|
||||
void on_channelsRefresh_clicked();
|
||||
void vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||
void vorData_sectionResized(int logicalIndex, int oldSize, int newSize);
|
||||
|
@ -120,7 +120,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="magDecAdjust">
|
||||
<widget class="ButtonSwitch" name="magDecAdjust">
|
||||
<property name="toolTip">
|
||||
<string>Draw radials adjusted for magnetic declination</string>
|
||||
</property>
|
||||
@ -139,6 +139,124 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rrTimeLabel">
|
||||
<property name="text">
|
||||
<string>RR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="rrTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Round robin turn time (s)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rrTimeText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sound volume (%)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>20s</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="centerShiftLabel">
|
||||
<property name="text">
|
||||
<string>Sh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="centerShift">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Center frequency shift (kHz)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-40</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="centerShiftText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>20k</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
@ -159,7 +277,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="channelsLabel">
|
||||
<property name="text">
|
||||
<string>VORs</string>
|
||||
<string>Chan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -264,7 +382,7 @@
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Offset (kHz)</string>
|
||||
<string>Nav Id</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Offset of the VOR's frequency from the current center frequency. Red indicates out of range.</string>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "vorlocalizerreport.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportFreqOffset, Message)
|
||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportRadial, Message)
|
||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportIdent, Message)
|
||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportChannels, Message)
|
||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportServiceddVORs, Message)
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define INCLUDE_VORLOCALIZERREPORT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
|
||||
#include "util/message.h"
|
||||
|
||||
@ -90,33 +91,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MsgReportFreqOffset : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getSubChannelId() const { return m_subChannelId; }
|
||||
int getFreqOffset() const { return m_freqOffset; }
|
||||
bool getOutOfBand() const { return m_outOfBand; }
|
||||
|
||||
static MsgReportFreqOffset* create(int subChannelId, int freqOffset, bool outOfBand)
|
||||
{
|
||||
return new MsgReportFreqOffset(subChannelId, freqOffset, outOfBand);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_subChannelId;
|
||||
int m_freqOffset;
|
||||
bool m_outOfBand;
|
||||
|
||||
MsgReportFreqOffset(int subChannelId, int freqOffset, bool outOfBand) :
|
||||
Message(),
|
||||
m_subChannelId(subChannelId),
|
||||
m_freqOffset(freqOffset),
|
||||
m_outOfBand(outOfBand)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class MsgReportIdent : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
@ -164,6 +138,26 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
class MsgReportServiceddVORs : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
std::vector<int>& getNavIds() { return m_navIds; }
|
||||
QHash<int, bool>& getSinglePlans() { return m_singlePlans; }
|
||||
|
||||
static MsgReportServiceddVORs* create() {
|
||||
return new MsgReportServiceddVORs();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> m_navIds;
|
||||
QHash<int, bool> m_singlePlans;
|
||||
|
||||
MsgReportServiceddVORs() :
|
||||
Message()
|
||||
{}
|
||||
};
|
||||
|
||||
public:
|
||||
VORLocalizerReport() {}
|
||||
~VORLocalizerReport() {}
|
||||
|
@ -33,6 +33,8 @@ void VORLocalizerSettings::resetToDefaults()
|
||||
m_rgbColor = QColor(255, 255, 0).rgb();
|
||||
m_title = "VOR Localizer";
|
||||
m_magDecAdjust = true;
|
||||
m_rrTime = 20;
|
||||
m_centerShift = 20000;
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
@ -54,6 +56,8 @@ QByteArray VORLocalizerSettings::serialize() const
|
||||
s.writeU32(7, m_rgbColor);
|
||||
s.writeString(9, m_title);
|
||||
s.writeBool(10, m_magDecAdjust);
|
||||
s.writeS32(11, m_rrTime);
|
||||
s.writeS32(12, m_centerShift);
|
||||
s.writeBool(14, m_useReverseAPI);
|
||||
s.writeString(15, m_reverseAPIAddress);
|
||||
s.writeU32(16, m_reverseAPIPort);
|
||||
@ -91,6 +95,8 @@ bool VORLocalizerSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(7, &m_rgbColor);
|
||||
d.readString(9, &m_title, "VOR Localizer");
|
||||
d.readBool(10, &m_magDecAdjust, true);
|
||||
d.readS32(11, &m_rrTime, 20);
|
||||
d.readS32(12, &m_centerShift, 20000);
|
||||
d.readBool(14, &m_useReverseAPI, false);
|
||||
d.readString(15, &m_reverseAPIAddress, "127.0.0.1");
|
||||
d.readU32(16, &utmp, 0);
|
||||
@ -123,4 +129,14 @@ bool VORLocalizerSettings::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
bool VORLocalizerSettings::VORChannel::operator<(const VORChannel& other) const
|
||||
{
|
||||
if (m_frequency != other.m_frequency) {
|
||||
return m_frequency < other.m_frequency;
|
||||
}
|
||||
if (m_subChannelId != other.m_subChannelId) {
|
||||
return m_subChannelId < other.m_subChannelId;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <QHash>
|
||||
|
||||
class Serializable;
|
||||
class ChannelAPI;
|
||||
|
||||
// Number of columns in the table
|
||||
|
||||
@ -34,15 +35,38 @@ struct VORLocalizerSubChannelSettings {
|
||||
|
||||
struct VORLocalizerSettings
|
||||
{
|
||||
struct VORDemodChannels
|
||||
struct VORChannel
|
||||
{
|
||||
int m_subChannelId; //!< Unique VOR identifier (from database)
|
||||
int m_frequency; //!< Frequency the VOR is on
|
||||
bool m_audioMute; //!< Mute the audio from this VOR
|
||||
|
||||
VORChannel() = default;
|
||||
VORChannel(const VORChannel&) = default;
|
||||
VORChannel& operator=(const VORChannel&) = default;
|
||||
|
||||
bool operator<(const VORChannel& other) const;
|
||||
};
|
||||
|
||||
struct AvailableChannel
|
||||
{
|
||||
int m_deviceSetIndex;
|
||||
int m_channelIndex;
|
||||
ChannelAPI *m_channelAPI;
|
||||
quint64 m_deviceCenterFrequency;
|
||||
int m_basebandSampleRate;
|
||||
int m_navId;
|
||||
|
||||
AvailableChannel() = default;
|
||||
AvailableChannel(const AvailableChannel&) = default;
|
||||
AvailableChannel& operator=(const AvailableChannel&) = default;
|
||||
};
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
bool m_magDecAdjust; //!< Adjust for magnetic declination when drawing radials on the map
|
||||
int m_rrTime; //!< Round robin turn time in seconds
|
||||
int m_centerShift; //!< Center frequency shift to apply to move away from DC
|
||||
bool m_useReverseAPI;
|
||||
QString m_reverseAPIAddress;
|
||||
uint16_t m_reverseAPIPort;
|
||||
@ -53,7 +77,7 @@ struct VORLocalizerSettings
|
||||
static const int VORDEMOD_COLUMNS = 11;
|
||||
static const int VOR_COL_NAME = 0;
|
||||
static const int VOR_COL_FREQUENCY = 1;
|
||||
static const int VOR_COL_OFFSET = 2;
|
||||
static const int VOR_COL_NAVID = 2;
|
||||
static const int VOR_COL_IDENT = 3;
|
||||
static const int VOR_COL_MORSE = 4;
|
||||
static const int VOR_COL_RX_IDENT = 5;
|
||||
@ -66,7 +90,7 @@ struct VORLocalizerSettings
|
||||
int m_columnIndexes[VORDEMOD_COLUMNS];//!< How the columns are ordered in the table
|
||||
int m_columnSizes[VORDEMOD_COLUMNS]; //!< Size of the coumns in the table
|
||||
|
||||
QHash<int, VORLocalizerSubChannelSettings *> m_subChannelSettings;
|
||||
QHash<int, VORLocalizerSubChannelSettings> m_subChannelSettings;
|
||||
|
||||
VORLocalizerSettings();
|
||||
void resetToDefaults();
|
||||
|
@ -18,12 +18,15 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "SWGDeviceState.h"
|
||||
#include "SWGDeviceSettings.h"
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGSuccessResponse.h"
|
||||
#include "SWGErrorResponse.h"
|
||||
|
||||
#include "webapi/webapiadapterinterface.h"
|
||||
#include "device/deviceset.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "webapi/webapiadapterinterface.h"
|
||||
#include "webapi/webapiutils.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "vorlocalizerreport.h"
|
||||
@ -36,7 +39,8 @@ class DSPDeviceSourceEngine;
|
||||
|
||||
VorLocalizerWorker::VorLocalizerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||
m_webAPIAdapterInterface(webAPIAdapterInterface),
|
||||
m_msgQueueToGUI(nullptr),
|
||||
m_msgQueueToFeature(nullptr),
|
||||
m_availableChannels(nullptr),
|
||||
m_running(false),
|
||||
m_mutex(QMutex::Recursive)
|
||||
{
|
||||
@ -59,6 +63,8 @@ bool VorLocalizerWorker::startWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
connect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn()));
|
||||
m_rrTimer.start(m_settings.m_rrTime * 1000);
|
||||
m_running = true;
|
||||
return m_running;
|
||||
}
|
||||
@ -66,6 +72,8 @@ bool VorLocalizerWorker::startWork()
|
||||
void VorLocalizerWorker::stopWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_rrTimer.stop();
|
||||
disconnect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn()));
|
||||
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
m_running = false;
|
||||
}
|
||||
@ -98,6 +106,7 @@ bool VorLocalizerWorker::handleMessage(const Message& cmd)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::handleMessage: MsgRefreshChannels";
|
||||
updateChannels();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -124,28 +133,53 @@ void VorLocalizerWorker::applySettings(const VORLocalizerSettings& settings, boo
|
||||
}
|
||||
|
||||
// Add new sub channels
|
||||
QHash<int, VORLocalizerSubChannelSettings *>::const_iterator itr = settings.m_subChannelSettings.begin();
|
||||
QHash<int, VORLocalizerSubChannelSettings>::const_iterator itr = settings.m_subChannelSettings.begin();
|
||||
|
||||
while (itr != settings.m_subChannelSettings.end())
|
||||
{
|
||||
VORLocalizerSubChannelSettings *subChannelSettings = itr.value();
|
||||
const VORLocalizerSubChannelSettings& subChannelSettings = itr.value();
|
||||
qDebug() << "VorLocalizerWorker::applySettings: subchannel " << subChannelSettings.m_id;
|
||||
int j = 0;
|
||||
|
||||
for (; j < m_vorChannels.size(); j++)
|
||||
{
|
||||
if (subChannelSettings->m_id == m_vorChannels[j].m_subChannelId)
|
||||
if (subChannelSettings.m_id == m_vorChannels[j].m_subChannelId)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::applySettings: subchannel "
|
||||
<< subChannelSettings.m_id
|
||||
<< "already present";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == m_vorChannels.size())
|
||||
{
|
||||
// Add a sub-channel sink
|
||||
qDebug() << "VorLocalizerWorker::applySettings: Adding sink " << subChannelSettings->m_id;
|
||||
qDebug() << "VorLocalizerWorker::applySettings: Adding subchannel " << subChannelSettings.m_id;
|
||||
addVORChannel(subChannelSettings);
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
|
||||
for (auto subChannelSetting : settings.m_subChannelSettings)
|
||||
{
|
||||
int navId = subChannelSetting.m_id;
|
||||
|
||||
if (m_settings.m_subChannelSettings.contains(navId))
|
||||
{
|
||||
if (subChannelSetting.m_audioMute != m_settings.m_subChannelSettings[navId].m_audioMute)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::applySettings: audioMute:" << subChannelSetting.m_audioMute;
|
||||
setAudioMute(navId, subChannelSetting.m_audioMute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings.m_rrTime != m_settings.m_rrTime) || force) {
|
||||
m_rrTimer.start(settings.m_rrTime * 1000);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
@ -159,6 +193,8 @@ void VorLocalizerWorker::updateHardware()
|
||||
|
||||
void VorLocalizerWorker::removeVORChannel(int navId)
|
||||
{
|
||||
qDebug("VorLocalizerWorker::removeVORChannel: %d", navId);
|
||||
|
||||
for (int i = 0; i < m_vorChannels.size(); i++)
|
||||
{
|
||||
if (m_vorChannels[i].m_subChannelId == navId)
|
||||
@ -167,57 +203,538 @@ void VorLocalizerWorker::removeVORChannel(int navId)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateChannels();
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::addVORChannel(const VORLocalizerSubChannelSettings *subChannelSettings)
|
||||
void VorLocalizerWorker::addVORChannel(const VORLocalizerSubChannelSettings& subChannelSettings)
|
||||
{
|
||||
VORChannel vorChannel = VORChannel{subChannelSettings->m_id, subChannelSettings->m_frequency, subChannelSettings->m_audioMute};
|
||||
qDebug("VorLocalizerWorker::addVORChannel: %d at %d Hz",
|
||||
subChannelSettings.m_id, subChannelSettings.m_frequency);
|
||||
|
||||
VORLocalizerSettings::VORChannel vorChannel =
|
||||
VORLocalizerSettings::VORChannel{
|
||||
subChannelSettings.m_id,
|
||||
subChannelSettings.m_frequency,
|
||||
subChannelSettings.m_audioMute
|
||||
};
|
||||
m_vorChannels.push_back(vorChannel);
|
||||
updateChannels();
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::updateChannels()
|
||||
{
|
||||
MainCore *mainCore = MainCore::instance();
|
||||
std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets();
|
||||
std::vector<DeviceSet*>::const_iterator it = deviceSets.begin();
|
||||
m_availableChannels.clear();
|
||||
qDebug() << "VorLocalizerWorker::updateChannels: "
|
||||
<< "#VORs:" << m_vorChannels.size()
|
||||
<< "#Chans:" << m_availableChannels->size();
|
||||
|
||||
int deviceIndex = 0;
|
||||
if ((m_vorChannels.size() == 0) || (m_availableChannels->size() == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; it != deviceSets.end(); ++it, deviceIndex++)
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
std::sort(m_vorChannels.begin(), m_vorChannels.end());
|
||||
std::vector<RRTurnPlan> devicesChannels;
|
||||
getChannelsByDevice(m_availableChannels, devicesChannels);
|
||||
QList<VORLocalizerSettings::VORChannel> unallocatedVORs(m_vorChannels);
|
||||
m_rrPlans.clear();
|
||||
int deviceCount = 0;
|
||||
|
||||
for (auto deviceChannel : devicesChannels)
|
||||
{
|
||||
DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine;
|
||||
unsigned int nbChannels = unallocatedVORs.size() < (int) deviceChannel.m_channels.size() ?
|
||||
unallocatedVORs.size() :
|
||||
deviceChannel.m_channels.size();
|
||||
std::vector<VORRange> vorRanges;
|
||||
|
||||
if (deviceSourceEngine)
|
||||
while (nbChannels != 0)
|
||||
{
|
||||
for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++)
|
||||
{
|
||||
ChannelAPI *channel = (*it)->getChannelAt(chi);
|
||||
getVORRanges(unallocatedVORs, nbChannels, vorRanges);
|
||||
filterVORRanges(vorRanges, deviceChannel.m_bandwidth);
|
||||
|
||||
if (channel->getURI() == "sdrangel.channel.vordemodsc")
|
||||
if (vorRanges.size() != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
nbChannels--;
|
||||
}
|
||||
|
||||
std::vector<QList<VORLocalizerSettings::VORChannel>> vorLists;
|
||||
|
||||
for (auto vorRange : vorRanges)
|
||||
{
|
||||
QList<VORLocalizerSettings::VORChannel> vorList;
|
||||
|
||||
for (auto index : vorRange.m_vorIndices) {
|
||||
vorList.append(VORLocalizerSettings::VORChannel(unallocatedVORs[index]));
|
||||
}
|
||||
|
||||
vorLists.push_back(vorList);
|
||||
}
|
||||
|
||||
// make one round robin turn for each VOR list for this device
|
||||
std::vector<RRTurnPlan> rrDevicePlans;
|
||||
|
||||
for (auto vorList : vorLists)
|
||||
{
|
||||
RRTurnPlan turnPlan(deviceChannel);
|
||||
int fMin = vorList.front().m_frequency;
|
||||
int fMax = vorList.back().m_frequency;
|
||||
int devFreq = (fMin + fMax) / 2;
|
||||
turnPlan.m_device.m_frequency = devFreq;
|
||||
int iCh = 0;
|
||||
|
||||
// qDebug() << "RR build plan "
|
||||
// << "device:" << turnPlan.m_device.m_deviceIndex
|
||||
// << "freq:" << turnPlan.m_device.m_frequency;
|
||||
|
||||
for (auto vorChannel : vorList)
|
||||
{
|
||||
RRChannel& channel = turnPlan.m_channels[iCh];
|
||||
channel.m_frequencyShift = vorChannel.m_frequency - devFreq;
|
||||
channel.m_navId = vorChannel.m_subChannelId;
|
||||
// qDebug() << "VOR channel" << vorChannel.m_subChannelId
|
||||
// << "freq:" << vorChannel.m_frequency
|
||||
// << "channel:" << channel.m_channelIndex
|
||||
// << "shift:" << channel.m_frequencyShift;
|
||||
// remove VOR from the unallocated list
|
||||
QList<VORLocalizerSettings::VORChannel>::iterator it = unallocatedVORs.begin();
|
||||
while (it != unallocatedVORs.end())
|
||||
{
|
||||
AvailableChannel availableChannel = AvailableChannel{deviceIndex, chi, channel};
|
||||
m_availableChannels.push_back(availableChannel);
|
||||
if (it->m_subChannelId == vorChannel.m_subChannelId) {
|
||||
it = unallocatedVORs.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
iCh++;
|
||||
}
|
||||
|
||||
rrDevicePlans.push_back(turnPlan);
|
||||
}
|
||||
|
||||
m_rrPlans.push_back(rrDevicePlans);
|
||||
deviceCount++;
|
||||
}
|
||||
|
||||
qDebug() << "VorLocalizerWorker::updateChannels: unallocatedVORs size:" << unallocatedVORs.size();
|
||||
|
||||
// Fallback for unallocated VORs: add single channel plans for all unallocated VORs
|
||||
if ((unallocatedVORs.size() != 0) && (devicesChannels.size() != 0) && m_rrPlans.size() != 0)
|
||||
{
|
||||
VorLocalizerWorker::RRTurnPlan& deviceChannel = devicesChannels.front();
|
||||
std::vector<VORRange> vorRanges;
|
||||
getVORRanges(unallocatedVORs, 1, vorRanges);
|
||||
std::vector<VorLocalizerWorker::RRTurnPlan>& rrPlan = m_rrPlans.front();
|
||||
std::vector<QList<VORLocalizerSettings::VORChannel>> vorLists;
|
||||
|
||||
for (auto vorRange : vorRanges)
|
||||
{
|
||||
QList<VORLocalizerSettings::VORChannel> vorList;
|
||||
|
||||
for (auto index : vorRange.m_vorIndices) {
|
||||
vorList.append(VORLocalizerSettings::VORChannel(unallocatedVORs[index]));
|
||||
}
|
||||
|
||||
vorLists.push_back(vorList);
|
||||
}
|
||||
|
||||
for (auto vorList : vorLists)
|
||||
{
|
||||
RRTurnPlan turnPlan(deviceChannel);
|
||||
int fMin = vorList.front().m_frequency;
|
||||
int fMax = vorList.back().m_frequency;
|
||||
int devFreq = (fMin + fMax) / 2;
|
||||
turnPlan.m_device.m_frequency = devFreq;
|
||||
int iCh = 0;
|
||||
|
||||
// qDebug() << "RR build plan "
|
||||
// << "device:" << turnPlan.m_device.m_deviceIndex
|
||||
// << "freq:" << turnPlan.m_device.m_frequency;
|
||||
|
||||
for (auto vorChannel : vorList)
|
||||
{
|
||||
RRChannel& channel = turnPlan.m_channels[iCh];
|
||||
channel.m_frequencyShift = vorChannel.m_frequency - devFreq;
|
||||
channel.m_navId = vorChannel.m_subChannelId;
|
||||
// qDebug() << "VOR channel" << vorChannel.m_subChannelId
|
||||
// << "freq:" << vorChannel.m_frequency
|
||||
// << "channel:" << channel.m_channelIndex
|
||||
// << "shift:" << channel.m_frequencyShift;
|
||||
iCh++;
|
||||
}
|
||||
|
||||
rrPlan.push_back(turnPlan);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto rrPlans : m_rrPlans)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::updateChannels: RR plans for one device";
|
||||
|
||||
for (auto rrPlan : rrPlans)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::updateChannels: RR plan: "
|
||||
<< "device:" << rrPlan.m_device.m_deviceIndex
|
||||
<< "frequency:" << rrPlan.m_device.m_frequency;
|
||||
|
||||
for (auto rrChannel : rrPlan.m_channels)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::updateChannels: RR channel: "
|
||||
<< "channel:" << rrChannel.m_channelAPI
|
||||
<< "index:" << rrChannel.m_channelIndex
|
||||
<< "shift:" << rrChannel.m_frequencyShift
|
||||
<< "navId:" << rrChannel.m_navId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_msgQueueToGUI)
|
||||
m_rrTurnCounters.resize(deviceCount);
|
||||
std::fill(m_rrTurnCounters.begin(), m_rrTurnCounters.end(), 0);
|
||||
rrNextTurn();
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::allocateChannel(ChannelAPI *channel, int vorFrequency, int vorNavId, int channelShift)
|
||||
{
|
||||
VORLocalizerSettings::AvailableChannel& availableChannel = m_availableChannels->operator[](channel);
|
||||
qDebug() << "VorLocalizerWorker::allocateChannel:"
|
||||
<< " vorNavId:" << vorNavId
|
||||
<< " vorFrequency:" << vorFrequency
|
||||
<< " channelShift:" << channelShift
|
||||
<< " deviceIndex:" << availableChannel.m_deviceSetIndex
|
||||
<< " channelIndex:" << availableChannel.m_channelIndex;
|
||||
double deviceFrequency = vorFrequency - channelShift;
|
||||
setDeviceFrequency(availableChannel.m_deviceSetIndex, deviceFrequency);
|
||||
setChannelShift(availableChannel.m_deviceSetIndex, availableChannel.m_channelIndex, channelShift, vorNavId);
|
||||
availableChannel.m_navId = vorNavId;
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::setDeviceFrequency(int deviceIndex, double targetFrequency)
|
||||
{
|
||||
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
|
||||
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||
int httpRC;
|
||||
|
||||
// Get current device center frequency
|
||||
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(
|
||||
deviceIndex,
|
||||
deviceSettingsResponse,
|
||||
errorResponse
|
||||
);
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
VORLocalizerReport::MsgReportChannels *msg = VORLocalizerReport::MsgReportChannels::create();
|
||||
std::vector<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msg->getChannels();
|
||||
qWarning("VorLocalizerWorker::setDeviceFrequency: get device frequency error %d: %s",
|
||||
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_availableChannels.size(); i++)
|
||||
{
|
||||
VORLocalizerReport::MsgReportChannels::Channel msgChannel =
|
||||
VORLocalizerReport::MsgReportChannels::Channel{
|
||||
m_availableChannels[i].m_deviceSetIndex,
|
||||
m_availableChannels[i].m_channelIndex
|
||||
};
|
||||
msgChannels.push_back(msgChannel);
|
||||
}
|
||||
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
|
||||
|
||||
m_msgQueueToGUI->push(msg);
|
||||
// Update centerFrequency
|
||||
WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", targetFrequency);
|
||||
QStringList deviceSettingsKeys;
|
||||
deviceSettingsKeys.append("centerFrequency");
|
||||
deviceSettingsResponse.init();
|
||||
deviceSettingsResponse.fromJsonObject(*jsonObj);
|
||||
SWGSDRangel::SWGErrorResponse errorResponse2;
|
||||
|
||||
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch(
|
||||
deviceIndex,
|
||||
false, // PATCH
|
||||
deviceSettingsKeys,
|
||||
deviceSettingsResponse,
|
||||
errorResponse2
|
||||
);
|
||||
|
||||
if (httpRC/100 == 2)
|
||||
{
|
||||
qDebug("VorLocalizerWorker::setDeviceFrequency: set device frequency %f OK", targetFrequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setDeviceFrequency: set device frequency error %d: %s",
|
||||
httpRC, qPrintable(*errorResponse2.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::setChannelShift(int deviceIndex, int channelIndex, double targetOffset, int vorNavId)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||
int httpRC;
|
||||
|
||||
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
||||
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
||||
deviceIndex,
|
||||
channelIndex,
|
||||
channelSettingsResponse,
|
||||
errorResponse
|
||||
);
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setChannelShift: get channel offset frequency error %d: %s",
|
||||
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||
}
|
||||
|
||||
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||
|
||||
if (!WebAPIUtils::setSubObjectDouble(*jsonObj, "inputFrequencyOffset", targetOffset))
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setChannelShift: No inputFrequencyOffset key in channel settings");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "navId", vorNavId))
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setChannelShift: No navId key in channel settings");
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList channelSettingsKeys;
|
||||
|
||||
if (m_settings.m_subChannelSettings.contains(vorNavId))
|
||||
{
|
||||
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "audioMute", m_settings.m_subChannelSettings[vorNavId].m_audioMute ? 1 : 0)) {
|
||||
qWarning("VorLocalizerWorker::setChannelShift: No audioMute key in channel settings");
|
||||
} else {
|
||||
channelSettingsKeys.append("audioMute");
|
||||
}
|
||||
}
|
||||
|
||||
channelSettingsKeys.append("inputFrequencyOffset");
|
||||
channelSettingsKeys.append("navId");
|
||||
channelSettingsResponse.init();
|
||||
channelSettingsResponse.fromJsonObject(*jsonObj);
|
||||
|
||||
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
||||
deviceIndex,
|
||||
channelIndex,
|
||||
false, // PATCH
|
||||
channelSettingsKeys,
|
||||
channelSettingsResponse,
|
||||
errorResponse
|
||||
);
|
||||
|
||||
if (httpRC/100 == 2)
|
||||
{
|
||||
qDebug("VorLocalizerWorker::setChannelShift: inputFrequencyOffset: %f navId: %d OK", targetOffset, vorNavId);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setChannelShift: set inputFrequencyOffset and navId error %d: %s",
|
||||
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::setAudioMute(int vorNavId, bool audioMute)
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
|
||||
if (!m_channelAllocations.contains(vorNavId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||
int httpRC;
|
||||
int deviceIndex = m_channelAllocations[vorNavId].m_deviceIndex;
|
||||
int channelIndex = m_channelAllocations[vorNavId].m_channelIndex;
|
||||
|
||||
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
||||
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
||||
deviceIndex,
|
||||
channelIndex,
|
||||
channelSettingsResponse,
|
||||
errorResponse
|
||||
);
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setChannelShift: get channel offset frequency error %d: %s",
|
||||
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||
}
|
||||
|
||||
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||
|
||||
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "audioMute", audioMute ? 1 : 0))
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setAudioMute: No audioMute key in channel settings");
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList channelSettingsKeys;
|
||||
channelSettingsKeys.append("audioMute");
|
||||
channelSettingsResponse.init();
|
||||
channelSettingsResponse.fromJsonObject(*jsonObj);
|
||||
|
||||
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
||||
deviceIndex,
|
||||
channelIndex,
|
||||
false, // PATCH
|
||||
channelSettingsKeys,
|
||||
channelSettingsResponse,
|
||||
errorResponse
|
||||
);
|
||||
|
||||
if (httpRC/100 == 2)
|
||||
{
|
||||
qDebug("VorLocalizerWorker::setAudioMute: navId: %d audioMute: %d OK", vorNavId, audioMute ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("VorLocalizerWorker::setAudioMute: navId: %d set audioMute error %d: %s",
|
||||
vorNavId, httpRC, qPrintable(*errorResponse.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::generateIndexCombinations(int length, int subLength, std::vector<std::vector<int>>& indexCombinations)
|
||||
{
|
||||
indexCombinations.clear();
|
||||
std::vector<int> sublist(subLength);
|
||||
std::vector<int>::iterator first = sublist.begin(), last = sublist.end();
|
||||
std::iota(first, last, 0);
|
||||
indexCombinations.push_back(sublist);
|
||||
|
||||
while ((*first) != length - subLength)
|
||||
{
|
||||
std::vector<int>::iterator mt = last;
|
||||
|
||||
while (*(--mt) == length-(last-mt));
|
||||
(*mt)++;
|
||||
while (++mt != last) *mt = *(mt-1)+1;
|
||||
|
||||
indexCombinations.push_back(std::vector<int>(first, last));
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::getVORRanges(const QList<VORLocalizerSettings::VORChannel>& vors, int subLength, std::vector<VORRange>& vorRanges)
|
||||
{
|
||||
std::vector<std::vector<int>> indexCombinations;
|
||||
generateIndexCombinations(vors.size(), subLength, indexCombinations);
|
||||
vorRanges.clear();
|
||||
|
||||
for (auto indexCombination : indexCombinations)
|
||||
{
|
||||
int fMax = vors.at(indexCombination.back()).m_frequency;
|
||||
int fMin = vors.at(indexCombination.front()).m_frequency;
|
||||
vorRanges.push_back(VORRange{indexCombination, fMax - fMin});
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::filterVORRanges(std::vector<VORRange>& vorRanges, int thresholdBW)
|
||||
{
|
||||
std::vector<VORRange> originalVORRanges(vorRanges.size());
|
||||
std::copy(vorRanges.begin(), vorRanges.end(), originalVORRanges.begin());
|
||||
vorRanges.clear();
|
||||
|
||||
for (auto vorRange : originalVORRanges)
|
||||
{
|
||||
if (vorRange.m_frequencyRange < thresholdBW) {
|
||||
vorRanges.push_back(vorRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::getChannelsByDevice(
|
||||
const QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *availableChannels,
|
||||
std::vector<RRTurnPlan>& devicesChannels
|
||||
)
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool operator()(const RRTurnPlan& a, const RRTurnPlan& b)
|
||||
{
|
||||
unsigned int nbChannelsA = a.m_channels.size();
|
||||
unsigned int nbChannelsB = a.m_channels.size();
|
||||
|
||||
if (nbChannelsA == nbChannelsB) {
|
||||
return a.m_bandwidth > b.m_bandwidth;
|
||||
} else {
|
||||
return nbChannelsA > nbChannelsB;
|
||||
}
|
||||
}
|
||||
} rrTurnPlanGreater;
|
||||
|
||||
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::const_iterator itr = availableChannels->begin();
|
||||
QMap<int, RRTurnPlan> devicesChannelsMap;
|
||||
|
||||
for (; itr != availableChannels->end(); ++itr)
|
||||
{
|
||||
devicesChannelsMap[itr->m_deviceSetIndex].m_device.m_deviceIndex = itr->m_deviceSetIndex;
|
||||
devicesChannelsMap[itr->m_deviceSetIndex].m_bandwidth = itr->m_basebandSampleRate;
|
||||
devicesChannelsMap[itr->m_deviceSetIndex].m_channels.push_back(RRChannel{itr->m_channelAPI, itr->m_channelIndex, 0, -1});
|
||||
}
|
||||
|
||||
QMap<int, RRTurnPlan>::const_iterator itm = devicesChannelsMap.begin();
|
||||
devicesChannels.clear();
|
||||
|
||||
for (; itm != devicesChannelsMap.end(); ++itm) {
|
||||
devicesChannels.push_back(*itm);
|
||||
}
|
||||
|
||||
std::sort(devicesChannels.begin(), devicesChannels.end(), rrTurnPlanGreater);
|
||||
}
|
||||
|
||||
void VorLocalizerWorker::rrNextTurn()
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
int iDevPlan = 0;
|
||||
VORLocalizerReport::MsgReportServiceddVORs *msg = VORLocalizerReport::MsgReportServiceddVORs::create();
|
||||
m_channelAllocations.clear();
|
||||
|
||||
for (auto rrPlan : m_rrPlans)
|
||||
{
|
||||
unsigned int turnCount = m_rrTurnCounters[iDevPlan];
|
||||
int deviceIndex = rrPlan[turnCount].m_device.m_deviceIndex;
|
||||
int deviceFrequency = rrPlan[turnCount].m_device.m_frequency - m_settings.m_centerShift;
|
||||
qDebug() << "VorLocalizerWorker::rrNextTurn: "
|
||||
<< "turn:" << turnCount
|
||||
<< "device:" << deviceIndex
|
||||
<< "frequency:" << deviceFrequency - m_settings.m_centerShift;
|
||||
setDeviceFrequency(deviceIndex, deviceFrequency);
|
||||
|
||||
for (auto channel : rrPlan[turnCount].m_channels)
|
||||
{
|
||||
qDebug() << "VorLocalizerWorker::rrNextTurn: "
|
||||
<< "device:" << deviceIndex
|
||||
<< "channel:" << channel.m_channelIndex
|
||||
<< "shift:" << channel.m_frequencyShift + m_settings.m_centerShift
|
||||
<< "navId:" << channel.m_navId;
|
||||
setChannelShift(
|
||||
deviceIndex,
|
||||
channel.m_channelIndex,
|
||||
channel.m_frequencyShift + m_settings.m_centerShift,
|
||||
channel.m_navId
|
||||
);
|
||||
m_channelAllocations[channel.m_navId] = ChannelAllocation{
|
||||
channel.m_navId,
|
||||
deviceIndex,
|
||||
channel.m_channelIndex
|
||||
};
|
||||
|
||||
if(m_availableChannels->contains(channel.m_channelAPI))
|
||||
{
|
||||
VORLocalizerSettings::AvailableChannel& availableChannel = m_availableChannels->operator[](channel.m_channelAPI);
|
||||
availableChannel.m_navId = channel.m_navId;
|
||||
}
|
||||
|
||||
msg->getNavIds().push_back(channel.m_navId);
|
||||
msg->getSinglePlans()[channel.m_navId] = (rrPlan.size() == 1);
|
||||
}
|
||||
|
||||
turnCount++;
|
||||
|
||||
if (turnCount == rrPlan.size()) {
|
||||
turnCount = 0;
|
||||
}
|
||||
|
||||
m_rrTurnCounters[iDevPlan] = turnCount;
|
||||
iDevPlan++;
|
||||
}
|
||||
|
||||
if (m_msgQueueToFeature) {
|
||||
m_msgQueueToFeature->push(msg);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
class WebAPIAdapterInterface;
|
||||
class ChannelAPI;
|
||||
class Feature;
|
||||
|
||||
class VorLocalizerWorker : public QObject
|
||||
{
|
||||
@ -77,42 +78,98 @@ public:
|
||||
void stopWork();
|
||||
bool isRunning() const { return m_running; }
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; }
|
||||
void setMessageQueueToFeature(MessageQueue *messageQueue) { m_msgQueueToFeature = messageQueue; }
|
||||
void setAvailableChannels(QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *avaialbleChannels) {
|
||||
m_availableChannels = avaialbleChannels;
|
||||
}
|
||||
|
||||
private:
|
||||
struct VORChannel
|
||||
struct VORRange
|
||||
{
|
||||
int m_subChannelId; //!< Unique VOR identifier (from database)
|
||||
int m_frequency; //!< Frequency the VOR is on
|
||||
bool m_audioMute; //!< Mute the audio from this VOR
|
||||
std::vector<int> m_vorIndices;
|
||||
int m_frequencyRange;
|
||||
|
||||
VORRange() = default;
|
||||
VORRange(const VORRange&) = default;
|
||||
VORRange& operator=(const VORRange&) = default;
|
||||
};
|
||||
|
||||
struct AvailableChannel
|
||||
struct RRDevice
|
||||
{
|
||||
int m_deviceIndex;
|
||||
int m_frequency;
|
||||
|
||||
RRDevice() = default;
|
||||
RRDevice(const RRDevice&) = default;
|
||||
RRDevice& operator=(const RRDevice&) = default;
|
||||
};
|
||||
|
||||
struct RRChannel
|
||||
{
|
||||
int m_deviceSetIndex;
|
||||
int m_channelIndex;
|
||||
ChannelAPI *m_channelAPI;
|
||||
int m_channelIndex;
|
||||
int m_frequencyShift;
|
||||
int m_navId;
|
||||
|
||||
RRChannel() = default;
|
||||
RRChannel(const RRChannel&) = default;
|
||||
RRChannel& operator=(const RRChannel&) = default;
|
||||
};
|
||||
|
||||
struct RRTurnPlan
|
||||
{
|
||||
RRDevice m_device;
|
||||
int m_bandwidth;
|
||||
std::vector<RRChannel> m_channels;
|
||||
|
||||
RRTurnPlan() = default;
|
||||
RRTurnPlan(const RRTurnPlan&) = default;
|
||||
RRTurnPlan& operator=(const RRTurnPlan&) = default;
|
||||
};
|
||||
|
||||
struct ChannelAllocation
|
||||
{
|
||||
int m_navId;
|
||||
int m_deviceIndex;
|
||||
int m_channelIndex;
|
||||
|
||||
ChannelAllocation() = default;
|
||||
ChannelAllocation(const ChannelAllocation&) = default;
|
||||
ChannelAllocation& operator=(const ChannelAllocation&) = default;
|
||||
};
|
||||
|
||||
WebAPIAdapterInterface *m_webAPIAdapterInterface;
|
||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||
MessageQueue *m_msgQueueToGUI; //!< Queue to report state to GUI
|
||||
MessageQueue *m_msgQueueToFeature; //!< Queue to report state to GUI
|
||||
VORLocalizerSettings m_settings;
|
||||
QList<VORChannel> m_vorChannels;
|
||||
QList<AvailableChannel> m_availableChannels;
|
||||
QList<VORLocalizerSettings::VORChannel> m_vorChannels;
|
||||
QHash<int, ChannelAllocation> m_channelAllocations;
|
||||
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *m_availableChannels;
|
||||
bool m_running;
|
||||
QTimer m_updateTimer;
|
||||
QMutex m_mutex;
|
||||
QTimer m_rrTimer;
|
||||
std::vector<std::vector<RRTurnPlan>> m_rrPlans; //!< Round robin plans for each device
|
||||
std::vector<int> m_rrTurnCounters; //!< Round robin turn count for each device
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
||||
void updateChannels();
|
||||
void removeVORChannel(int navId);
|
||||
void addVORChannel(const VORLocalizerSubChannelSettings *subChannelSettings);
|
||||
void addVORChannel(const VORLocalizerSubChannelSettings& subChannelSettings);
|
||||
void updateChannels(); //!< (re)allocate channels to service VORs
|
||||
void allocateChannel(ChannelAPI *channel, int vorFrequency, int vorNavId, int channelShift);
|
||||
void setDeviceFrequency(int deviceIndex, double targetFrequency);
|
||||
void setChannelShift(int deviceIndex, int channelIndex, double targetOffset, int vorNavId);
|
||||
void setAudioMute(int vorNavId, bool audioMute);
|
||||
static void generateIndexCombinations(int length, int subLength, std::vector<std::vector<int>>& indexCombinations);
|
||||
static void getVORRanges(const QList<VORLocalizerSettings::VORChannel>& vors, int subLength, std::vector<VORRange>& vorRanges);
|
||||
static void filterVORRanges(std::vector<VORRange>& vorRanges, int thresholdBW);
|
||||
static void getChannelsByDevice(const QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *availableChannels, std::vector<RRTurnPlan>& m_deviceChannels);
|
||||
|
||||
private slots:
|
||||
void handleInputMessages();
|
||||
void updateHardware();
|
||||
void rrNextTurn();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_VORLOCALIZERWORKER_H_
|
||||
|
@ -46,7 +46,7 @@ MessagePipes::~MessagePipes()
|
||||
}
|
||||
}
|
||||
|
||||
void MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type)
|
||||
MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type)
|
||||
{
|
||||
int typeId;
|
||||
|
||||
@ -68,8 +68,11 @@ void MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feat
|
||||
m_featureRegistrations.insert(regKey, QList<const Feature*>());
|
||||
}
|
||||
|
||||
m_messageRegistrations[regKey].append(new MessageQueue());
|
||||
MessageQueue *messageQueue = new MessageQueue();
|
||||
m_messageRegistrations[regKey].append(messageQueue);
|
||||
m_featureRegistrations[regKey].append(feature);
|
||||
|
||||
return messageQueue;
|
||||
}
|
||||
|
||||
QList<MessageQueue*>* MessagePipes::getMessageQueues(const ChannelAPI *source, const QString& type)
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
MessagePipes& operator=(const MessagePipes&) = delete;
|
||||
~MessagePipes();
|
||||
|
||||
void registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type);
|
||||
MessageQueue *registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type);
|
||||
QList<MessageQueue*>* getMessageQueues(const ChannelAPI *source, const QString& type);
|
||||
|
||||
private:
|
||||
|
@ -9484,20 +9484,36 @@ margin-bottom: 20px;
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"navId" : {
|
||||
"type" : "integer",
|
||||
"description" : "VOR unique identifier when set by VOR localizer feature"
|
||||
},
|
||||
"radial" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current detected radial"
|
||||
"description" : "current detected radial (degrees)"
|
||||
},
|
||||
"refMag" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current reference signal magnitude"
|
||||
"description" : "current reference signal magnitude (dB)"
|
||||
},
|
||||
"varMag" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current variable signal magnitude"
|
||||
"description" : "current variable signal magnitude (dB)"
|
||||
},
|
||||
"validRadial" : {
|
||||
"type" : "integer",
|
||||
"description" : "Radial validity estimation\n * 0 - Radial is invalid\n * 1 - Radial is valid\n"
|
||||
},
|
||||
"validRefMag" : {
|
||||
"type" : "integer",
|
||||
"description" : "Reference signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||
},
|
||||
"validVarMag" : {
|
||||
"type" : "integer",
|
||||
"description" : "Variable signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||
},
|
||||
"morseIdent" : {
|
||||
"type" : "string",
|
||||
@ -9645,6 +9661,14 @@ margin-bottom: 20px;
|
||||
"magDecAdjust" : {
|
||||
"type" : "integer",
|
||||
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
||||
},
|
||||
"rrTime" : {
|
||||
"type" : "integer",
|
||||
"description" : "Round robin turn time in seconds"
|
||||
},
|
||||
"centerShift" : {
|
||||
"type" : "integer",
|
||||
"description" : "Shift of center frequency in Hz"
|
||||
}
|
||||
},
|
||||
"description" : "VORLocalizer"
|
||||
@ -44850,7 +44874,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2020-11-29T21:00:18.945+01:00
|
||||
Generated 2020-12-06T23:43:21.772+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,18 +55,39 @@ VORDemodSCReport:
|
||||
volume:
|
||||
type: number
|
||||
format: float
|
||||
navId:
|
||||
description: VOR unique identifier when set by VOR localizer feature
|
||||
type: integer
|
||||
radial:
|
||||
description: current detected radial
|
||||
description: current detected radial (degrees)
|
||||
type: number
|
||||
format: float
|
||||
refMag:
|
||||
description: current reference signal magnitude
|
||||
description: current reference signal magnitude (dB)
|
||||
type: number
|
||||
format: float
|
||||
varMag:
|
||||
description: current variable signal magnitude
|
||||
description: current variable signal magnitude (dB)
|
||||
type: number
|
||||
format: float
|
||||
validRadial:
|
||||
type: integer
|
||||
description: >
|
||||
Radial validity estimation
|
||||
* 0 - Radial is invalid
|
||||
* 1 - Radial is valid
|
||||
validRefMag:
|
||||
type: integer
|
||||
description: >
|
||||
Reference signal magnitude validity
|
||||
* 0 - Magnitude below threshold
|
||||
* 1 - Magnitude above threshold
|
||||
validVarMag:
|
||||
type: integer
|
||||
description: >
|
||||
Variable signal magnitude validity
|
||||
* 0 - Magnitude below threshold
|
||||
* 1 - Magnitude above threshold
|
||||
morseIdent:
|
||||
description: current identification morse code transcript
|
||||
type: string
|
||||
|
@ -19,3 +19,9 @@ VORLocalizerSettings:
|
||||
magDecAdjust:
|
||||
description: Adjust radial lines on map for magnetic declination of VOR
|
||||
type: integer
|
||||
rrTime:
|
||||
description: Round robin turn time in seconds
|
||||
type: integer
|
||||
centerShift:
|
||||
description: Shift of center frequency in Hz
|
||||
type: integer
|
||||
|
59
sdrbase/util/average.h
Normal file
59
sdrbase/util/average.h
Normal file
@ -0,0 +1,59 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _UTIL_AVERAGE_H_
|
||||
#define _UTIL_AVERAGE_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <typename T, typename Total>
|
||||
class AverageUtil
|
||||
{
|
||||
public:
|
||||
AverageUtil()
|
||||
: m_numSamples(0), m_total(0)
|
||||
{ }
|
||||
|
||||
AverageUtil(T sample)
|
||||
: m_numSamples(1), m_total(sample)
|
||||
{ }
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_numSamples = 0;
|
||||
m_total = 0;
|
||||
}
|
||||
|
||||
void operator()(T sample)
|
||||
{
|
||||
m_total += sample;
|
||||
m_numSamples++;
|
||||
}
|
||||
|
||||
double asDouble() const { return ((double)m_total) / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||
float asFloat() const { return ((float)m_total) / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||
operator T() const { return m_total / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||
T instantAverage() const { return m_total / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||
int getNumSamples() const { return m_numSamples; }
|
||||
|
||||
private:
|
||||
int m_numSamples;
|
||||
Total m_total;
|
||||
};
|
||||
|
||||
#endif /* _UTIL_AVERAGE_H_ */
|
@ -344,6 +344,51 @@ bool WebAPIUtils::setSubObjectDouble(QJsonObject &json, const QString &key, doub
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get integer value from within nested JSON object
|
||||
bool WebAPIUtils::getSubObjectInt(const QJsonObject &json, const QString &key, int &value)
|
||||
{
|
||||
for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++)
|
||||
{
|
||||
QJsonValue jsonValue = it.value();
|
||||
|
||||
if (jsonValue.isObject())
|
||||
{
|
||||
QJsonObject subObject = jsonValue.toObject();
|
||||
|
||||
if (subObject.contains(key))
|
||||
{
|
||||
value = subObject[key].toInt();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set integer value withing nested JSON object
|
||||
bool WebAPIUtils::setSubObjectInt(QJsonObject &json, const QString &key, int value)
|
||||
{
|
||||
for (QJsonObject::iterator it = json.begin(); it != json.end(); it++)
|
||||
{
|
||||
QJsonValue jsonValue = it.value();
|
||||
|
||||
if (jsonValue.isObject())
|
||||
{
|
||||
QJsonObject subObject = jsonValue.toObject();
|
||||
|
||||
if (subObject.contains(key))
|
||||
{
|
||||
subObject[key] = value;
|
||||
it.value() = subObject;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// look for value in key=value
|
||||
bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value)
|
||||
{
|
||||
|
@ -47,6 +47,8 @@ public:
|
||||
static bool getObjectObjects(const QJsonObject &json, const QString &key, QList<QJsonObject> &objects);
|
||||
static bool getSubObjectDouble(const QJsonObject &json, const QString &key, double &value);
|
||||
static bool setSubObjectDouble(QJsonObject &json, const QString &key, double value);
|
||||
static bool getSubObjectInt(const QJsonObject &json, const QString &key, int &value);
|
||||
static bool setSubObjectInt(QJsonObject &json, const QString &key, int value);
|
||||
static bool extractValue(const QJsonObject &json, const QString &key, QJsonValue &value);
|
||||
static bool extractArray(const QJsonObject &json, const QString &key, QJsonArray &value);
|
||||
static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value);
|
||||
|
@ -55,18 +55,39 @@ VORDemodSCReport:
|
||||
volume:
|
||||
type: number
|
||||
format: float
|
||||
navId:
|
||||
description: VOR unique identifier when set by VOR localizer feature
|
||||
type: integer
|
||||
radial:
|
||||
description: current detected radial
|
||||
description: current detected radial (degrees)
|
||||
type: number
|
||||
format: float
|
||||
refMag:
|
||||
description: current reference signal magnitude
|
||||
description: current reference signal magnitude (dB)
|
||||
type: number
|
||||
format: float
|
||||
varMag:
|
||||
description: current variable signal magnitude
|
||||
description: current variable signal magnitude (dB)
|
||||
type: number
|
||||
format: float
|
||||
validRadial:
|
||||
type: integer
|
||||
description: >
|
||||
Radial validity estimation
|
||||
* 0 - Radial is invalid
|
||||
* 1 - Radial is valid
|
||||
validRefMag:
|
||||
type: integer
|
||||
description: >
|
||||
Reference signal magnitude validity
|
||||
* 0 - Magnitude below threshold
|
||||
* 1 - Magnitude above threshold
|
||||
validVarMag:
|
||||
type: integer
|
||||
description: >
|
||||
Variable signal magnitude validity
|
||||
* 0 - Magnitude below threshold
|
||||
* 1 - Magnitude above threshold
|
||||
morseIdent:
|
||||
description: current identification morse code transcript
|
||||
type: string
|
||||
|
@ -19,3 +19,9 @@ VORLocalizerSettings:
|
||||
magDecAdjust:
|
||||
description: Adjust radial lines on map for magnetic declination of VOR
|
||||
type: integer
|
||||
rrTime:
|
||||
description: Round robin turn time in seconds
|
||||
type: integer
|
||||
centerShift:
|
||||
description: Shift of center frequency in Hz
|
||||
type: integer
|
||||
|
@ -9484,20 +9484,36 @@ margin-bottom: 20px;
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"navId" : {
|
||||
"type" : "integer",
|
||||
"description" : "VOR unique identifier when set by VOR localizer feature"
|
||||
},
|
||||
"radial" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current detected radial"
|
||||
"description" : "current detected radial (degrees)"
|
||||
},
|
||||
"refMag" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current reference signal magnitude"
|
||||
"description" : "current reference signal magnitude (dB)"
|
||||
},
|
||||
"varMag" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "current variable signal magnitude"
|
||||
"description" : "current variable signal magnitude (dB)"
|
||||
},
|
||||
"validRadial" : {
|
||||
"type" : "integer",
|
||||
"description" : "Radial validity estimation\n * 0 - Radial is invalid\n * 1 - Radial is valid\n"
|
||||
},
|
||||
"validRefMag" : {
|
||||
"type" : "integer",
|
||||
"description" : "Reference signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||
},
|
||||
"validVarMag" : {
|
||||
"type" : "integer",
|
||||
"description" : "Variable signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||
},
|
||||
"morseIdent" : {
|
||||
"type" : "string",
|
||||
@ -9645,6 +9661,14 @@ margin-bottom: 20px;
|
||||
"magDecAdjust" : {
|
||||
"type" : "integer",
|
||||
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
||||
},
|
||||
"rrTime" : {
|
||||
"type" : "integer",
|
||||
"description" : "Round robin turn time in seconds"
|
||||
},
|
||||
"centerShift" : {
|
||||
"type" : "integer",
|
||||
"description" : "Shift of center frequency in Hz"
|
||||
}
|
||||
},
|
||||
"description" : "VORLocalizer"
|
||||
@ -44850,7 +44874,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2020-11-29T21:00:18.945+01:00
|
||||
Generated 2020-12-06T23:43:21.772+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,12 +36,20 @@ SWGVORDemodSCReport::SWGVORDemodSCReport() {
|
||||
m_audio_sample_rate_isSet = false;
|
||||
volume = 0.0f;
|
||||
m_volume_isSet = false;
|
||||
nav_id = 0;
|
||||
m_nav_id_isSet = false;
|
||||
radial = 0.0f;
|
||||
m_radial_isSet = false;
|
||||
ref_mag = 0.0f;
|
||||
m_ref_mag_isSet = false;
|
||||
var_mag = 0.0f;
|
||||
m_var_mag_isSet = false;
|
||||
valid_radial = 0;
|
||||
m_valid_radial_isSet = false;
|
||||
valid_ref_mag = 0;
|
||||
m_valid_ref_mag_isSet = false;
|
||||
valid_var_mag = 0;
|
||||
m_valid_var_mag_isSet = false;
|
||||
morse_ident = nullptr;
|
||||
m_morse_ident_isSet = false;
|
||||
}
|
||||
@ -60,12 +68,20 @@ SWGVORDemodSCReport::init() {
|
||||
m_audio_sample_rate_isSet = false;
|
||||
volume = 0.0f;
|
||||
m_volume_isSet = false;
|
||||
nav_id = 0;
|
||||
m_nav_id_isSet = false;
|
||||
radial = 0.0f;
|
||||
m_radial_isSet = false;
|
||||
ref_mag = 0.0f;
|
||||
m_ref_mag_isSet = false;
|
||||
var_mag = 0.0f;
|
||||
m_var_mag_isSet = false;
|
||||
valid_radial = 0;
|
||||
m_valid_radial_isSet = false;
|
||||
valid_ref_mag = 0;
|
||||
m_valid_ref_mag_isSet = false;
|
||||
valid_var_mag = 0;
|
||||
m_valid_var_mag_isSet = false;
|
||||
morse_ident = new QString("");
|
||||
m_morse_ident_isSet = false;
|
||||
}
|
||||
@ -79,6 +95,10 @@ SWGVORDemodSCReport::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(morse_ident != nullptr) {
|
||||
delete morse_ident;
|
||||
}
|
||||
@ -103,12 +123,20 @@ SWGVORDemodSCReport::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&volume, pJson["volume"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&nav_id, pJson["navId"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&radial, pJson["radial"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&ref_mag, pJson["refMag"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&var_mag, pJson["varMag"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&valid_radial, pJson["validRadial"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&valid_ref_mag, pJson["validRefMag"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&valid_var_mag, pJson["validVarMag"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&morse_ident, pJson["morseIdent"], "QString", "QString");
|
||||
|
||||
}
|
||||
@ -139,6 +167,9 @@ SWGVORDemodSCReport::asJsonObject() {
|
||||
if(m_volume_isSet){
|
||||
obj->insert("volume", QJsonValue(volume));
|
||||
}
|
||||
if(m_nav_id_isSet){
|
||||
obj->insert("navId", QJsonValue(nav_id));
|
||||
}
|
||||
if(m_radial_isSet){
|
||||
obj->insert("radial", QJsonValue(radial));
|
||||
}
|
||||
@ -148,6 +179,15 @@ SWGVORDemodSCReport::asJsonObject() {
|
||||
if(m_var_mag_isSet){
|
||||
obj->insert("varMag", QJsonValue(var_mag));
|
||||
}
|
||||
if(m_valid_radial_isSet){
|
||||
obj->insert("validRadial", QJsonValue(valid_radial));
|
||||
}
|
||||
if(m_valid_ref_mag_isSet){
|
||||
obj->insert("validRefMag", QJsonValue(valid_ref_mag));
|
||||
}
|
||||
if(m_valid_var_mag_isSet){
|
||||
obj->insert("validVarMag", QJsonValue(valid_var_mag));
|
||||
}
|
||||
if(morse_ident != nullptr && *morse_ident != QString("")){
|
||||
toJsonValue(QString("morseIdent"), morse_ident, obj, QString("QString"));
|
||||
}
|
||||
@ -195,6 +235,16 @@ SWGVORDemodSCReport::setVolume(float volume) {
|
||||
this->m_volume_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORDemodSCReport::getNavId() {
|
||||
return nav_id;
|
||||
}
|
||||
void
|
||||
SWGVORDemodSCReport::setNavId(qint32 nav_id) {
|
||||
this->nav_id = nav_id;
|
||||
this->m_nav_id_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGVORDemodSCReport::getRadial() {
|
||||
return radial;
|
||||
@ -225,6 +275,36 @@ SWGVORDemodSCReport::setVarMag(float var_mag) {
|
||||
this->m_var_mag_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORDemodSCReport::getValidRadial() {
|
||||
return valid_radial;
|
||||
}
|
||||
void
|
||||
SWGVORDemodSCReport::setValidRadial(qint32 valid_radial) {
|
||||
this->valid_radial = valid_radial;
|
||||
this->m_valid_radial_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORDemodSCReport::getValidRefMag() {
|
||||
return valid_ref_mag;
|
||||
}
|
||||
void
|
||||
SWGVORDemodSCReport::setValidRefMag(qint32 valid_ref_mag) {
|
||||
this->valid_ref_mag = valid_ref_mag;
|
||||
this->m_valid_ref_mag_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORDemodSCReport::getValidVarMag() {
|
||||
return valid_var_mag;
|
||||
}
|
||||
void
|
||||
SWGVORDemodSCReport::setValidVarMag(qint32 valid_var_mag) {
|
||||
this->valid_var_mag = valid_var_mag;
|
||||
this->m_valid_var_mag_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGVORDemodSCReport::getMorseIdent() {
|
||||
return morse_ident;
|
||||
@ -252,6 +332,9 @@ SWGVORDemodSCReport::isSet(){
|
||||
if(m_volume_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_nav_id_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_radial_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
@ -261,6 +344,15 @@ SWGVORDemodSCReport::isSet(){
|
||||
if(m_var_mag_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_valid_radial_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_valid_ref_mag_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_valid_var_mag_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(morse_ident && *morse_ident != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -54,6 +54,9 @@ public:
|
||||
float getVolume();
|
||||
void setVolume(float volume);
|
||||
|
||||
qint32 getNavId();
|
||||
void setNavId(qint32 nav_id);
|
||||
|
||||
float getRadial();
|
||||
void setRadial(float radial);
|
||||
|
||||
@ -63,6 +66,15 @@ public:
|
||||
float getVarMag();
|
||||
void setVarMag(float var_mag);
|
||||
|
||||
qint32 getValidRadial();
|
||||
void setValidRadial(qint32 valid_radial);
|
||||
|
||||
qint32 getValidRefMag();
|
||||
void setValidRefMag(qint32 valid_ref_mag);
|
||||
|
||||
qint32 getValidVarMag();
|
||||
void setValidVarMag(qint32 valid_var_mag);
|
||||
|
||||
QString* getMorseIdent();
|
||||
void setMorseIdent(QString* morse_ident);
|
||||
|
||||
@ -82,6 +94,9 @@ private:
|
||||
float volume;
|
||||
bool m_volume_isSet;
|
||||
|
||||
qint32 nav_id;
|
||||
bool m_nav_id_isSet;
|
||||
|
||||
float radial;
|
||||
bool m_radial_isSet;
|
||||
|
||||
@ -91,6 +106,15 @@ private:
|
||||
float var_mag;
|
||||
bool m_var_mag_isSet;
|
||||
|
||||
qint32 valid_radial;
|
||||
bool m_valid_radial_isSet;
|
||||
|
||||
qint32 valid_ref_mag;
|
||||
bool m_valid_ref_mag_isSet;
|
||||
|
||||
qint32 valid_var_mag;
|
||||
bool m_valid_var_mag_isSet;
|
||||
|
||||
QString* morse_ident;
|
||||
bool m_morse_ident_isSet;
|
||||
|
||||
|
@ -44,6 +44,10 @@ SWGVORLocalizerSettings::SWGVORLocalizerSettings() {
|
||||
m_reverse_api_feature_index_isSet = false;
|
||||
mag_dec_adjust = 0;
|
||||
m_mag_dec_adjust_isSet = false;
|
||||
rr_time = 0;
|
||||
m_rr_time_isSet = false;
|
||||
center_shift = 0;
|
||||
m_center_shift_isSet = false;
|
||||
}
|
||||
|
||||
SWGVORLocalizerSettings::~SWGVORLocalizerSettings() {
|
||||
@ -68,6 +72,10 @@ SWGVORLocalizerSettings::init() {
|
||||
m_reverse_api_feature_index_isSet = false;
|
||||
mag_dec_adjust = 0;
|
||||
m_mag_dec_adjust_isSet = false;
|
||||
rr_time = 0;
|
||||
m_rr_time_isSet = false;
|
||||
center_shift = 0;
|
||||
m_center_shift_isSet = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -84,6 +92,8 @@ SWGVORLocalizerSettings::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
SWGVORLocalizerSettings*
|
||||
@ -113,6 +123,10 @@ SWGVORLocalizerSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&mag_dec_adjust, pJson["magDecAdjust"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rr_time, pJson["rrTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(¢er_shift, pJson["centerShift"], "qint32", "");
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
@ -153,6 +167,12 @@ SWGVORLocalizerSettings::asJsonObject() {
|
||||
if(m_mag_dec_adjust_isSet){
|
||||
obj->insert("magDecAdjust", QJsonValue(mag_dec_adjust));
|
||||
}
|
||||
if(m_rr_time_isSet){
|
||||
obj->insert("rrTime", QJsonValue(rr_time));
|
||||
}
|
||||
if(m_center_shift_isSet){
|
||||
obj->insert("centerShift", QJsonValue(center_shift));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -237,6 +257,26 @@ SWGVORLocalizerSettings::setMagDecAdjust(qint32 mag_dec_adjust) {
|
||||
this->m_mag_dec_adjust_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORLocalizerSettings::getRrTime() {
|
||||
return rr_time;
|
||||
}
|
||||
void
|
||||
SWGVORLocalizerSettings::setRrTime(qint32 rr_time) {
|
||||
this->rr_time = rr_time;
|
||||
this->m_rr_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGVORLocalizerSettings::getCenterShift() {
|
||||
return center_shift;
|
||||
}
|
||||
void
|
||||
SWGVORLocalizerSettings::setCenterShift(qint32 center_shift) {
|
||||
this->center_shift = center_shift;
|
||||
this->m_center_shift_isSet = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SWGVORLocalizerSettings::isSet(){
|
||||
@ -266,6 +306,12 @@ SWGVORLocalizerSettings::isSet(){
|
||||
if(m_mag_dec_adjust_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rr_time_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_center_shift_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
|
@ -66,6 +66,12 @@ public:
|
||||
qint32 getMagDecAdjust();
|
||||
void setMagDecAdjust(qint32 mag_dec_adjust);
|
||||
|
||||
qint32 getRrTime();
|
||||
void setRrTime(qint32 rr_time);
|
||||
|
||||
qint32 getCenterShift();
|
||||
void setCenterShift(qint32 center_shift);
|
||||
|
||||
|
||||
virtual bool isSet() override;
|
||||
|
||||
@ -94,6 +100,12 @@ private:
|
||||
qint32 mag_dec_adjust;
|
||||
bool m_mag_dec_adjust_isSet;
|
||||
|
||||
qint32 rr_time;
|
||||
bool m_rr_time_isSet;
|
||||
|
||||
qint32 center_shift;
|
||||
bool m_center_shift_isSet;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user