Add antenna tools feature

This commit is contained in:
Jon Beniston 2021-05-20 17:15:14 +01:00
parent 396e701d46
commit 1cd605e365
27 changed files with 2674 additions and 0 deletions

View File

@ -13,6 +13,7 @@ endif()
add_subdirectory(afc)
add_subdirectory(ais)
add_subdirectory(antennatools)
add_subdirectory(aprs)
add_subdirectory(demodanalyzer)
add_subdirectory(pertester)

View File

@ -0,0 +1,55 @@
project(antennatools)
set(antennatools_SOURCES
antennatools.cpp
antennatoolssettings.cpp
antennatoolsplugin.cpp
antennatoolswebapiadapter.cpp
)
set(antennatools_HEADERS
antennatools.h
antennatoolssettings.h
antennatoolsplugin.h
antennatoolswebapiadapter.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
if(NOT SERVER_MODE)
set(antennatools_SOURCES
${antennatools_SOURCES}
antennatoolsgui.cpp
antennatoolsgui.ui
antennatools.qrc
)
set(antennatools_HEADERS
${antennatools_HEADERS}
antennatoolsgui.h
)
set(TARGET_NAME antennatools)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME antennatoolssrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${antennatools_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -0,0 +1,275 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGFeatureSettings.h"
#include "SWGFeatureReport.h"
#include "SWGFeatureActions.h"
#include "SWGDeviceState.h"
#include "dsp/dspengine.h"
#include "device/deviceset.h"
#include "channel/channelapi.h"
#include "feature/featureset.h"
#include "maincore.h"
#include "antennatools.h"
MESSAGE_CLASS_DEFINITION(AntennaTools::MsgConfigureAntennaTools, Message)
const char* const AntennaTools::m_featureIdURI = "sdrangel.feature.antennatools";
const char* const AntennaTools::m_featureId = "AntennaTools";
AntennaTools::AntennaTools(WebAPIAdapterInterface *webAPIAdapterInterface) :
Feature(m_featureIdURI, webAPIAdapterInterface)
{
qDebug("AntennaTools::AntennaTools: webAPIAdapterInterface: %p", webAPIAdapterInterface);
setObjectName(m_featureId);
m_state = StIdle;
m_errorMessage = "AntennaTools error";
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
AntennaTools::~AntennaTools()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
}
bool AntennaTools::handleMessage(const Message& cmd)
{
if (MsgConfigureAntennaTools::match(cmd))
{
MsgConfigureAntennaTools& cfg = (MsgConfigureAntennaTools&) cmd;
qDebug() << "AntennaTools::handleMessage: MsgConfigureAntennaTools";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else
{
return false;
}
}
QByteArray AntennaTools::serialize() const
{
return m_settings.serialize();
}
bool AntennaTools::deserialize(const QByteArray& data)
{
if (m_settings.deserialize(data))
{
MsgConfigureAntennaTools *msg = MsgConfigureAntennaTools::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureAntennaTools *msg = MsgConfigureAntennaTools::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
void AntennaTools::applySettings(const AntennaToolsSettings& settings, bool force)
{
qDebug() << "AntennaTools::applySettings:"
<< " m_title: " << settings.m_title
<< " m_rgbColor: " << settings.m_rgbColor
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< " m_reverseAPIPort: " << settings.m_reverseAPIPort
<< " m_reverseAPIFeatureSetIndex: " << settings.m_reverseAPIFeatureSetIndex
<< " m_reverseAPIFeatureIndex: " << settings.m_reverseAPIFeatureIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((m_settings.m_title != settings.m_title) || force) {
reverseAPIKeys.append("title");
}
if ((m_settings.m_rgbColor != settings.m_rgbColor) || force) {
reverseAPIKeys.append("rgbColor");
}
if (settings.m_useReverseAPI)
{
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
(m_settings.m_reverseAPIFeatureSetIndex != settings.m_reverseAPIFeatureSetIndex) ||
(m_settings.m_reverseAPIFeatureIndex != settings.m_reverseAPIFeatureIndex);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
m_settings = settings;
}
int AntennaTools::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAntennaToolsSettings(new SWGSDRangel::SWGAntennaToolsSettings());
response.getAntennaToolsSettings()->init();
webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int AntennaTools::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
AntennaToolsSettings settings = m_settings;
webapiUpdateFeatureSettings(settings, featureSettingsKeys, response);
MsgConfigureAntennaTools *msg = MsgConfigureAntennaTools::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureAntennaTools *msgToGUI = MsgConfigureAntennaTools::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatFeatureSettings(response, settings);
return 200;
}
void AntennaTools::webapiFormatFeatureSettings(
SWGSDRangel::SWGFeatureSettings& response,
const AntennaToolsSettings& settings)
{
if (response.getAntennaToolsSettings()->getTitle()) {
*response.getAntennaToolsSettings()->getTitle() = settings.m_title;
} else {
response.getAntennaToolsSettings()->setTitle(new QString(settings.m_title));
}
response.getAntennaToolsSettings()->setRgbColor(settings.m_rgbColor);
response.getAntennaToolsSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getAntennaToolsSettings()->getReverseApiAddress()) {
*response.getAntennaToolsSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getAntennaToolsSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getAntennaToolsSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getAntennaToolsSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIFeatureSetIndex);
response.getAntennaToolsSettings()->setReverseApiChannelIndex(settings.m_reverseAPIFeatureIndex);
}
void AntennaTools::webapiUpdateFeatureSettings(
AntennaToolsSettings& settings,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response)
{
if (featureSettingsKeys.contains("title")) {
settings.m_title = *response.getAntennaToolsSettings()->getTitle();
}
if (featureSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getAntennaToolsSettings()->getRgbColor();
}
if (featureSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getAntennaToolsSettings()->getUseReverseApi() != 0;
}
if (featureSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getAntennaToolsSettings()->getReverseApiAddress();
}
if (featureSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getAntennaToolsSettings()->getReverseApiPort();
}
if (featureSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIFeatureSetIndex = response.getAntennaToolsSettings()->getReverseApiDeviceIndex();
}
if (featureSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIFeatureIndex = response.getAntennaToolsSettings()->getReverseApiChannelIndex();
}
}
void AntennaTools::webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AntennaToolsSettings& settings, bool force)
{
SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = new SWGSDRangel::SWGFeatureSettings();
// swgFeatureSettings->setOriginatorFeatureIndex(getIndexInDeviceSet());
// swgFeatureSettings->setOriginatorFeatureSetIndex(getDeviceSetIndex());
swgFeatureSettings->setFeatureType(new QString("AntennaTools"));
swgFeatureSettings->setAntennaToolsSettings(new SWGSDRangel::SWGAntennaToolsSettings());
SWGSDRangel::SWGAntennaToolsSettings *swgAntennaToolsSettings = swgFeatureSettings->getAntennaToolsSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (featureSettingsKeys.contains("title") || force) {
swgAntennaToolsSettings->setTitle(new QString(settings.m_title));
}
if (featureSettingsKeys.contains("rgbColor") || force) {
swgAntennaToolsSettings->setRgbColor(settings.m_rgbColor);
}
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
.arg(settings.m_reverseAPIAddress)
.arg(settings.m_reverseAPIPort)
.arg(settings.m_reverseAPIFeatureSetIndex)
.arg(settings.m_reverseAPIFeatureIndex);
m_networkRequest.setUrl(QUrl(channelSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer = new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgFeatureSettings->asJson().toUtf8());
buffer->seek(0);
// Always use PATCH to avoid passing reverse API settings
QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
buffer->setParent(reply);
delete swgFeatureSettings;
}
void AntennaTools::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "AntennaTools::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("AntennaTools::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}

View File

@ -0,0 +1,113 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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 INCLUDE_FEATURE_ANTENNATOOLS_H_
#define INCLUDE_FEATURE_ANTENNATOOLS_H_
#include <QThread>
#include <QHash>
#include <QNetworkRequest>
#include <QTimer>
#include "feature/feature.h"
#include "util/message.h"
#include "antennatoolssettings.h"
class WebAPIAdapterInterface;
class QNetworkAccessManager;
class QNetworkReply;
namespace SWGSDRangel {
class SWGDeviceState;
}
class AntennaTools : public Feature
{
Q_OBJECT
public:
class MsgConfigureAntennaTools : public Message {
MESSAGE_CLASS_DECLARATION
public:
const AntennaToolsSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureAntennaTools* create(const AntennaToolsSettings& settings, bool force) {
return new MsgConfigureAntennaTools(settings, force);
}
private:
AntennaToolsSettings m_settings;
bool m_force;
MsgConfigureAntennaTools(const AntennaToolsSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
AntennaTools(WebAPIAdapterInterface *webAPIAdapterInterface);
virtual ~AntennaTools();
virtual void destroy() { delete this; }
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) const { id = objectName(); }
virtual void getTitle(QString& title) const { title = m_settings.m_title; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
static void webapiFormatFeatureSettings(
SWGSDRangel::SWGFeatureSettings& response,
const AntennaToolsSettings& settings);
static void webapiUpdateFeatureSettings(
AntennaToolsSettings& settings,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response);
static const char* const m_featureIdURI;
static const char* const m_featureId;
private:
QThread m_thread;
AntennaToolsSettings m_settings;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void applySettings(const AntennaToolsSettings& settings, bool force = false);
void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AntennaToolsSettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif // INCLUDE_FEATURE_ANTENNATOOLS_H_

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/antennatools/">
<file>antennatools/dipole.png</file>
<file>antennatools/dish.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,480 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <cmath>
#include "feature/featureuiset.h"
#include "gui/basicfeaturesettingsdialog.h"
#include "channel/channelwebapiutils.h"
#include "mainwindow.h"
#include "maincore.h"
#include "device/deviceuiset.h"
#include "util/units.h"
#include "ui_antennatoolsgui.h"
#include "antennatools.h"
#include "antennatoolsgui.h"
AntennaToolsGUI* AntennaToolsGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature)
{
AntennaToolsGUI* gui = new AntennaToolsGUI(pluginAPI, featureUISet, feature);
return gui;
}
void AntennaToolsGUI::destroy()
{
delete this;
}
void AntennaToolsGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray AntennaToolsGUI::serialize() const
{
return m_settings.serialize();
}
bool AntennaToolsGUI::deserialize(const QByteArray& data)
{
if (m_settings.deserialize(data))
{
displaySettings();
applySettings(true);
return true;
}
else
{
resetToDefaults();
return false;
}
}
bool AntennaToolsGUI::handleMessage(const Message& message)
{
if (AntennaTools::MsgConfigureAntennaTools::match(message))
{
qDebug("AntennaToolsGUI::handleMessage: AntennaTools::MsgConfigureAntennaTools");
const AntennaTools::MsgConfigureAntennaTools& cfg = (AntennaTools::MsgConfigureAntennaTools&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
return false;
}
void AntennaToolsGUI::handleInputMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()))
{
if (handleMessage(*message)) {
delete message;
}
}
}
void AntennaToolsGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
}
AntennaToolsGUI::AntennaToolsGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
FeatureGUI(parent),
ui(new Ui::AntennaToolsGUI),
m_pluginAPI(pluginAPI),
m_featureUISet(featureUISet),
m_doApplySettings(true),
m_deviceSets(0)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
setChannelWidget(false);
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
m_antennatools = reinterpret_cast<AntennaTools*>(feature);
m_antennatools->setMessageQueueToGUI(&m_inputMessageQueue);
m_featureUISet->addRollupWidget(this);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
// Rather than polling, could we get a message when frequencies change?
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
m_statusTimer.start(500);
displaySettings();
applySettings(true);
}
AntennaToolsGUI::~AntennaToolsGUI()
{
delete ui;
}
void AntennaToolsGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void AntennaToolsGUI::displaySettings()
{
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_settings.m_title);
blockApplySettings(true);
ui->dipoleFrequency->setValue(m_settings.m_dipoleFrequencyMHz);
ui->dipoleFrequencySelect->setCurrentIndex(m_settings.m_dipoleFrequencySelect);
ui->dipoleEndEffectFactor->setValue(m_settings.m_dipoleEndEffectFactor);
ui->dipoleLengthUnits->setCurrentIndex((int)m_settings.m_dipoleLengthUnits);
ui->dishFrequency->setValue(m_settings.m_dishFrequencyMHz);
ui->dishFrequencySelect->setCurrentIndex(m_settings.m_dishFrequencySelect);
ui->dishDiameter->setValue(m_settings.m_dishDiameter);
ui->dishDepth->setValue(m_settings.m_dishDepth);
ui->dishLengthUnits->setCurrentIndex((int)m_settings.m_dishLengthUnits);
ui->dishEfficiency->setValue(m_settings.m_dishEfficiency);
blockApplySettings(false);
calcDipoleLength();
calcDishFocalLength();
calcDishBeamwidth();
calcDishGain();
}
void AntennaToolsGUI::leaveEvent(QEvent*)
{
}
void AntennaToolsGUI::enterEvent(QEvent*)
{
}
void AntennaToolsGUI::onMenuDialogCalled(const QPoint &p)
{
if (m_contextMenuType == ContextMenuChannelSettings)
{
BasicFeatureSettingsDialog dialog(this);
dialog.setTitle(m_settings.m_title);
dialog.setColor(m_settings.m_rgbColor);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIFeatureSetIndex(m_settings.m_reverseAPIFeatureSetIndex);
dialog.setReverseAPIFeatureIndex(m_settings.m_reverseAPIFeatureIndex);
dialog.move(p);
dialog.exec();
m_settings.m_rgbColor = dialog.getColor().rgb();
m_settings.m_title = dialog.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIFeatureSetIndex = dialog.getReverseAPIFeatureSetIndex();
m_settings.m_reverseAPIFeatureIndex = dialog.getReverseAPIFeatureIndex();
setWindowTitle(m_settings.m_title);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
resetContextMenuType();
}
void AntennaToolsGUI::updateStatus()
{
// Update device sets listed in frequency select combos
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
if (deviceSets.size() < m_deviceSets)
{
int countToRemove = m_deviceSets - deviceSets.size();
for (int i = 0; i < countToRemove; i++)
{
ui->dipoleFrequencySelect->removeItem(ui->dipoleFrequencySelect->count() - 1);
ui->dishFrequencySelect->removeItem(ui->dishFrequencySelect->count() - 1);
}
}
else if (deviceSets.size() > m_deviceSets)
{
int countToAdd = deviceSets.size() - m_deviceSets;
for (int i = 0; i < countToAdd; i++)
{
ui->dipoleFrequencySelect->addItem(QString("Device set %1").arg(ui->dipoleFrequencySelect->count() - 1));
ui->dishFrequencySelect->addItem(QString("Device set %1").arg(ui->dishFrequencySelect->count() - 1));
}
}
m_deviceSets = deviceSets.size();
// Update frequencies to match device set centre frequency
if (m_settings.m_dipoleFrequencySelect >= 1)
{
double frequency = getDeviceSetFrequencyMHz(m_settings.m_dipoleFrequencySelect - 1);
if (frequency >= 0.0) {
ui->dipoleFrequency->setValue(frequency);
}
}
if (m_settings.m_dishFrequencySelect >= 1)
{
double frequency = getDeviceSetFrequencyMHz(m_settings.m_dishFrequencySelect - 1);
if (frequency >= 0.0) {
ui->dishFrequency->setValue(frequency);
}
}
}
void AntennaToolsGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
AntennaTools::MsgConfigureAntennaTools* message = AntennaTools::MsgConfigureAntennaTools::create(m_settings, force);
m_antennatools->getInputMessageQueue()->push(message);
}
}
void AntennaToolsGUI::calcDipoleLength()
{
// Length of dipole in freespace is half wavelength
// End effect depends on ratio of thickness to length, insulation and distance to ground.
// Is there a formula for this?
double lengthMetres = 0.5 * 299.792458 * m_settings.m_dipoleEndEffectFactor / m_settings.m_dipoleFrequencyMHz;
ui->dipoleLength->blockSignals(true);
ui->dipoleElementLength->blockSignals(true);
if (m_settings.m_dipoleLengthUnits == AntennaToolsSettings::M)
{
ui->dipoleLength->setValue(lengthMetres);
ui->dipoleElementLength->setValue(lengthMetres/2.0);
}
else if (m_settings.m_dipoleLengthUnits == AntennaToolsSettings::CM)
{
ui->dipoleLength->setValue(lengthMetres*100.0);
ui->dipoleElementLength->setValue(lengthMetres/2.0*100.0);
}
else
{
ui->dipoleLength->setValue(Units::metresToFeet(lengthMetres));
ui->dipoleElementLength->setValue(Units::metresToFeet(lengthMetres/2.0));
}
ui->dipoleLength->blockSignals(false);
ui->dipoleElementLength->blockSignals(false);
}
double AntennaToolsGUI::calcDipoleFrequency(double totalLength)
{
double lengthMetres;
if (m_settings.m_dipoleLengthUnits == AntennaToolsSettings::M) {
lengthMetres = totalLength;
} else if (m_settings.m_dipoleLengthUnits == AntennaToolsSettings::CM) {
lengthMetres = totalLength / 100.0;
} else {
lengthMetres = Units::feetToMetres(totalLength);
}
return 0.5 * 299.792458 * m_settings.m_dipoleEndEffectFactor / lengthMetres;
}
void AntennaToolsGUI::on_dipoleFrequencySelect_currentIndexChanged(int index)
{
m_settings.m_dipoleFrequencySelect = index;
applySettings();
if (index >= 1)
{
double frequency = getDeviceSetFrequencyMHz(index - 1);
if (frequency >= 0.0) {
ui->dipoleFrequency->setValue(frequency);
}
}
ui->dipoleFrequency->setReadOnly(index >= 1);
ui->dipoleLength->setReadOnly(index >= 1);
ui->dipoleElementLength->setReadOnly(index >= 1);
}
void AntennaToolsGUI::on_dipoleFrequency_valueChanged(double value)
{
m_settings.m_dipoleFrequencyMHz = value;
applySettings();
calcDipoleLength();
}
void AntennaToolsGUI::on_dipoleEndEffectFactor_valueChanged(double value)
{
m_settings.m_dipoleEndEffectFactor = value;
applySettings();
calcDipoleLength();
}
void AntennaToolsGUI::on_dipoleLengthUnits_currentIndexChanged(int index)
{
m_settings.m_dipoleLengthUnits = (AntennaToolsSettings::LengthUnits)index;
applySettings();
calcDipoleLength();
}
void AntennaToolsGUI::on_dipoleLength_valueChanged(double value)
{
m_settings.m_dipoleFrequencyMHz = calcDipoleFrequency(value);
applySettings();
ui->dipoleElementLength->blockSignals(true);
ui->dipoleElementLength->setValue(value/2.0);
ui->dipoleElementLength->blockSignals(false);
ui->dipoleFrequency->blockSignals(true);
ui->dipoleFrequency->setValue(m_settings.m_dipoleFrequencyMHz);
ui->dipoleFrequency->blockSignals(false);
}
void AntennaToolsGUI::on_dipoleElementLength_valueChanged(double value)
{
m_settings.m_dipoleFrequencyMHz = calcDipoleFrequency(value*2.0);
applySettings();
ui->dipoleLength->blockSignals(true);
ui->dipoleLength->setValue(value*2.0);
ui->dipoleLength->blockSignals(false);
ui->dipoleFrequency->blockSignals(true);
ui->dipoleFrequency->setValue(m_settings.m_dipoleFrequencyMHz);
ui->dipoleFrequency->blockSignals(false);
}
double AntennaToolsGUI::dishLambda() const
{
return 299.792458 / m_settings.m_dishFrequencyMHz;
}
double AntennaToolsGUI::dishLengthMetres(double length) const
{
if (m_settings.m_dishLengthUnits == AntennaToolsSettings::CM) {
return length / 100.0;
} else if (m_settings.m_dishLengthUnits == AntennaToolsSettings::M) {
return length;
} else {
return Units::feetToMetres(length);
}
}
double AntennaToolsGUI::dishDiameterMetres() const
{
return dishLengthMetres(m_settings.m_dishDiameter);
}
double AntennaToolsGUI::dishDepthMetres() const
{
return dishLengthMetres(m_settings.m_dishDepth);
}
void AntennaToolsGUI::calcDishFocalLength()
{
double d = dishDiameterMetres();
double focalLength = d * d / (16.0 * dishDepthMetres());
ui->dishFocalLength->setValue(focalLength);
double fd = focalLength / d;
ui->dishFD->setValue(fd);
}
void AntennaToolsGUI::calcDishBeamwidth()
{
double beamwidth = 70.0 * dishLambda() / dishDiameterMetres();
ui->dishBeamwidth->setValue(beamwidth);
}
void AntennaToolsGUI::calcDishGain()
{
double t = M_PI * dishDiameterMetres() / dishLambda();
double gainDB = 10.0 * log10((m_settings.m_dishEfficiency/100.0) * (t*t));
ui->dishGain->setValue(gainDB);
}
void AntennaToolsGUI::on_dishFrequency_valueChanged(double value)
{
m_settings.m_dishFrequencyMHz = value;
applySettings();
calcDishBeamwidth();
calcDishGain();
}
void AntennaToolsGUI::on_dishFrequencySelect_currentIndexChanged(int index)
{
m_settings.m_dishFrequencySelect = index;
applySettings();
if (index >= 1)
{
double frequency = getDeviceSetFrequencyMHz(index - 1);
if (frequency >= 0.0) {
ui->dishFrequency->setValue(frequency);
}
}
ui->dishFrequency->setReadOnly(index >= 1);
}
void AntennaToolsGUI::on_dishDiameter_valueChanged(double value)
{
m_settings.m_dishDiameter = value;
applySettings();
calcDishFocalLength();
calcDishBeamwidth();
calcDishGain();
}
void AntennaToolsGUI::on_dishLengthUnits_currentIndexChanged(int index)
{
m_settings.m_dishLengthUnits = (AntennaToolsSettings::LengthUnits)index;
applySettings();
calcDishFocalLength();
calcDishBeamwidth();
calcDishGain();
}
void AntennaToolsGUI::on_dishDepth_valueChanged(double value)
{
m_settings.m_dishDepth = value;
applySettings();
calcDishFocalLength();
}
void AntennaToolsGUI::on_dishEfficiency_valueChanged(int value)
{
m_settings.m_dishEfficiency = value;
applySettings();
calcDishGain();
}
double AntennaToolsGUI::getDeviceSetFrequencyMHz(int index)
{
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
if (index < deviceSets.size())
{
double frequencyInHz;
if (ChannelWebAPIUtils::getCenterFrequency(index, frequencyInHz))
{
return frequencyInHz / 1e6;
}
else
{
return -1.0;
}
}
else
{
return -1.0;
}
}

View File

@ -0,0 +1,103 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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 INCLUDE_FEATURE_ANTENNATOOLSGUI_H_
#define INCLUDE_FEATURE_ANTENNATOOLSGUI_H_
#include <QTimer>
#include <QAbstractListModel>
#include "feature/featuregui.h"
#include "util/messagequeue.h"
#include "pipes/pipeendpoint.h"
#include "antennatoolssettings.h"
class PluginAPI;
class FeatureUISet;
class AntennaTools;
namespace Ui {
class AntennaToolsGUI;
}
class AntennaToolsGUI : public FeatureGUI {
Q_OBJECT
public:
static AntennaToolsGUI* create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature);
virtual void destroy();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
private:
Ui::AntennaToolsGUI* ui;
PluginAPI* m_pluginAPI;
FeatureUISet* m_featureUISet;
AntennaToolsSettings m_settings;
bool m_doApplySettings;
AntennaTools* m_antennatools;
MessageQueue m_inputMessageQueue;
QTimer m_statusTimer;
int m_deviceSets;
explicit AntennaToolsGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
virtual ~AntennaToolsGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
bool handleMessage(const Message& message);
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void calcDipoleLength();
double calcDipoleFrequency(double totalLength);
void calcDishFocalLength();
void calcDishBeamwidth();
void calcDishGain();
double dishLambda() const;
double dishLengthMetres(double length) const;
double dishDiameterMetres() const;
double dishDepthMetres() const;
double getDeviceSetFrequencyMHz(int index);
private slots:
void on_dipoleFrequency_valueChanged(double value);
void on_dipoleFrequencySelect_currentIndexChanged(int index);
void on_dipoleEndEffectFactor_valueChanged(double value);
void on_dipoleLengthUnits_currentIndexChanged(int index);
void on_dipoleLength_valueChanged(double value);
void on_dipoleElementLength_valueChanged(double value);
void on_dishFrequency_valueChanged(double value);
void on_dishFrequencySelect_currentIndexChanged(int index);
void on_dishDiameter_valueChanged(double value);
void on_dishLengthUnits_currentIndexChanged(int index);
void on_dishDepth_valueChanged(double value);
void on_dishEfficiency_valueChanged(int value);
void onMenuDialogCalled(const QPoint &p);
void onWidgetRolled(QWidget* widget, bool rollDown);
void handleInputMessages();
void updateStatus();
};
#endif // INCLUDE_FEATURE_ANTENNATOOLSGUI_H_

View File

@ -0,0 +1,497 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AntennaToolsGUI</class>
<widget class="RollupWidget" name="AntennaToolsGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>377</width>
<height>461</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="windowTitle">
<string>Antenna Tools</string>
</property>
<property name="statusTip">
<string>AntennaTools</string>
</property>
<widget class="QTabWidget" name="tabWidget">
<property name="geometry">
<rect>
<x>16</x>
<y>19</y>
<width>351</width>
<height>431</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Calculators</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="dipoleTab">
<attribute name="title">
<string>Dipole</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QComboBox" name="dipoleFrequencySelect">
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<item>
<property name="text">
<string>MHz</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="dipoleFrequencyLabel">
<property name="text">
<string>Frequency</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="dipoleLength">
<property name="toolTip">
<string>Total length of dipole</string>
</property>
<property name="maximum">
<double>2000000000.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="dipoleLengthUnits">
<property name="toolTip">
<string>Units for lengths</string>
</property>
<item>
<property name="text">
<string>cm</string>
</property>
</item>
<item>
<property name="text">
<string>m</string>
</property>
</item>
<item>
<property name="text">
<string>feet</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="dipoleEndEffectFactor">
<property name="toolTip">
<string>End effect factor to correct for reactance</string>
</property>
<property name="minimum">
<double>0.900000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.950000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="dipoleElementLength">
<property name="toolTip">
<string>Dipole element length</string>
</property>
<property name="maximum">
<double>2000000000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="dipoleFrequency">
<property name="toolTip">
<string>Frequency to calculate the length for</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>100000.000000000000000</double>
</property>
<property name="value">
<double>2400.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="dipoleEndEffectFactorLabel">
<property name="text">
<string>End effect factor</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="dipoleElementLengthLabel">
<property name="text">
<string>Element length</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="dipoleLengthLabel">
<property name="text">
<string>Total length</string>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="dipoleVerticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" colspan="3">
<widget class="QLabel" name="dipoleImage">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="antennatools.qrc">:/antennatools/antennatools/dipole.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dishTab">
<attribute name="title">
<string>Dish</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="7" column="0">
<widget class="QLabel" name="dishBeamwidthLabel">
<property name="text">
<string>Beamwidth (°)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="dishFD">
<property name="toolTip">
<string>Focal length to diameter ratio</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="dishDiameteLabel">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QLabel" name="dishImage">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="antennatools.qrc">:/antennatools/antennatools/dish.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="dishFDLabel">
<property name="text">
<string>f/D</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="dishFrequencySelect">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string/>
</property>
<item>
<property name="text">
<string>MHz</string>
</property>
</item>
</widget>
</item>
<item row="9" column="1">
<widget class="QDoubleSpinBox" name="dishGain">
<property name="toolTip">
<string>Dish gain</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="dishEfficiency">
<property name="toolTip">
<string>Dish efficiency in percent</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="dishDepthLabel">
<property name="text">
<string>Depth</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="dishLengthUnits">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Units for lengths</string>
</property>
<item>
<property name="text">
<string>cm</string>
</property>
</item>
<item>
<property name="text">
<string>m</string>
</property>
</item>
<item>
<property name="text">
<string>feet</string>
</property>
</item>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="dishGainLabel">
<property name="text">
<string>Gain (dB)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QDoubleSpinBox" name="dishBeamwidth">
<property name="toolTip">
<string>Halfpower (-3dB) beamwidth in degrees</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="dishEfficiencyLabel">
<property name="text">
<string>Efficiency (%)</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="dishDepth">
<property name="toolTip">
<string>Depth of the dish</string>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="dishFrequency">
<property name="toolTip">
<string>Frequency of operation</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>20000.000000000000000</double>
</property>
<property name="value">
<double>2400.000000000000000</double>
</property>
</widget>
</item>
<item row="11" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="dishFrequencyLabel">
<property name="text">
<string>Frequency</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="dishDiameter">
<property name="toolTip">
<string>Diameter of the dish</string>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="dishFocalLengthLabel">
<property name="text">
<string>Focal length</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="dishFocalLength">
<property name="toolTip">
<string>Focal length</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>RollupWidget</class>
<extends>QWidget</extends>
<header>gui/rollupwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>dipoleFrequency</tabstop>
<tabstop>dipoleFrequencySelect</tabstop>
<tabstop>dipoleLength</tabstop>
<tabstop>dipoleLengthUnits</tabstop>
<tabstop>dipoleElementLength</tabstop>
<tabstop>dipoleEndEffectFactor</tabstop>
<tabstop>dishFrequency</tabstop>
<tabstop>dishFrequencySelect</tabstop>
<tabstop>dishDiameter</tabstop>
<tabstop>dishLengthUnits</tabstop>
<tabstop>dishDepth</tabstop>
<tabstop>dishFD</tabstop>
<tabstop>dishBeamwidth</tabstop>
<tabstop>dishGain</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
<include location="antennatools.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "antennatoolsgui.h"
#endif
#include "antennatools.h"
#include "antennatoolsplugin.h"
#include "antennatoolswebapiadapter.h"
const PluginDescriptor AntennaToolsPlugin::m_pluginDescriptor = {
AntennaTools::m_featureId,
QStringLiteral("Antenna Tools"),
QStringLiteral("6.12.2"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
AntennaToolsPlugin::AntennaToolsPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(nullptr)
{
}
const PluginDescriptor& AntennaToolsPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void AntennaToolsPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
m_pluginAPI->registerFeature(AntennaTools::m_featureIdURI, AntennaTools::m_featureId, this);
}
#ifdef SERVER_MODE
FeatureGUI* AntennaToolsPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
(void) featureUISet;
(void) feature;
return nullptr;
}
#else
FeatureGUI* AntennaToolsPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
return AntennaToolsGUI::create(m_pluginAPI, featureUISet, feature);
}
#endif
Feature* AntennaToolsPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const
{
return new AntennaTools(webAPIAdapterInterface);
}
FeatureWebAPIAdapter* AntennaToolsPlugin::createFeatureWebAPIAdapter() const
{
return new AntennaToolsWebAPIAdapter();
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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 INCLUDE_FEATURE_ANTENNATOOLSPLUGIN_H
#define INCLUDE_FEATURE_ANTENNATOOLSPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class FeatureGUI;
class WebAPIAdapterInterface;
class AntennaToolsPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.feature.antennatools")
public:
explicit AntennaToolsPlugin(QObject* parent = nullptr);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual FeatureGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const;
virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const;
virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif // INCLUDE_FEATURE_ANTENNATOOLSPLUGIN_H

View File

@ -0,0 +1,133 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QColor>
#include "util/simpleserializer.h"
#include "settings/serializable.h"
#include "antennatoolssettings.h"
AntennaToolsSettings::AntennaToolsSettings()
{
resetToDefaults();
}
void AntennaToolsSettings::resetToDefaults()
{
m_dipoleFrequencyMHz = 435.0;
m_dipoleFrequencySelect = 0;
m_dipoleEndEffectFactor = 0.95;
m_dipoleLengthUnits = CM;
m_dishFrequencyMHz = 1700.0;
m_dishFrequencySelect = 0;
m_dishDiameter = 240.0;
m_dishDepth = 30.0;
m_dishEfficiency = 60;
m_dishLengthUnits = CM;
m_title = "Antenna Tools";
m_rgbColor = QColor(225, 25, 99).rgb();
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIFeatureSetIndex = 0;
m_reverseAPIFeatureIndex = 0;
}
QByteArray AntennaToolsSettings::serialize() const
{
SimpleSerializer s(1);
s.writeDouble(1, m_dipoleFrequencyMHz);
s.writeS32(2, m_dipoleFrequencySelect);
s.writeDouble(3, m_dipoleEndEffectFactor);
s.writeS32(4, (int)m_dipoleLengthUnits);
s.writeDouble(5, m_dishFrequencyMHz);
s.writeS32(6, m_dishFrequencySelect);
s.writeDouble(7, m_dishDiameter);
s.writeDouble(8, m_dishDepth);
s.writeS32(9, m_dishEfficiency);
s.writeS32(10, (int)m_dishLengthUnits);
s.writeString(11, m_title);
s.writeU32(12, m_rgbColor);
s.writeBool(13, m_useReverseAPI);
s.writeString(14, m_reverseAPIAddress);
s.writeU32(15, m_reverseAPIPort);
s.writeU32(16, m_reverseAPIFeatureSetIndex);
s.writeU32(17, m_reverseAPIFeatureIndex);
return s.final();
}
bool AntennaToolsSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
QByteArray bytetmp;
uint32_t utmp;
QString strtmp;
d.readDouble(1, &m_dipoleFrequencyMHz, 435.0);
d.readS32(2, &m_dipoleFrequencySelect, 0);
d.readDouble(3, &m_dipoleEndEffectFactor, 0.95);
d.readS32(4, (int*)&m_dipoleLengthUnits, (int)CM);
d.readDouble(5, &m_dishFrequencyMHz, 1700.0);
d.readS32(6, &m_dishFrequencySelect, 0);
d.readDouble(7, &m_dishDiameter, 240.0);
d.readDouble(8, &m_dishDepth, 30.0);
d.readS32(9, &m_dishEfficiency, 60);
d.readS32(10, (int*)&m_dishLengthUnits, (int)CM);
d.readString(11, &m_title, "Antenna Tools");
d.readU32(12, &m_rgbColor, QColor(225, 25, 99).rgb());
d.readBool(13, &m_useReverseAPI, false);
d.readString(14, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(15, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(16, &utmp, 0);
m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp;
d.readU32(17, &utmp, 0);
m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp;
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,59 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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 INCLUDE_FEATURE_ANTENNATOOLSSETTINGS_H_
#define INCLUDE_FEATURE_ANTENNATOOLSSETTINGS_H_
#include <QByteArray>
#include <QString>
#include "util/message.h"
class Serializable;
struct AntennaToolsSettings
{
enum LengthUnits { CM, M, FEET };
double m_dipoleFrequencyMHz;
int m_dipoleFrequencySelect;
double m_dipoleEndEffectFactor;
LengthUnits m_dipoleLengthUnits;
double m_dishFrequencyMHz;
int m_dishFrequencySelect;
double m_dishDiameter;
double m_dishDepth;
int m_dishEfficiency;
LengthUnits m_dishLengthUnits;
QString m_title;
quint32 m_rgbColor;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIFeatureSetIndex;
uint16_t m_reverseAPIFeatureIndex;
AntennaToolsSettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif // INCLUDE_FEATURE_ANTENNATOOLSSETTINGS_H_

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "SWGFeatureSettings.h"
#include "antennatools.h"
#include "antennatoolswebapiadapter.h"
AntennaToolsWebAPIAdapter::AntennaToolsWebAPIAdapter()
{}
AntennaToolsWebAPIAdapter::~AntennaToolsWebAPIAdapter()
{}
int AntennaToolsWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAntennaToolsSettings(new SWGSDRangel::SWGAntennaToolsSettings());
response.getAntennaToolsSettings()->init();
AntennaTools::webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int AntennaToolsWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) force; // no action
(void) errorMessage;
AntennaTools::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// 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 INCLUDE_ANTENNATOOLS_WEBAPIADAPTER_H
#define INCLUDE_ANTENNATOOLS_WEBAPIADAPTER_H
#include "feature/featurewebapiadapter.h"
#include "antennatoolssettings.h"
/**
* Standalone API adapter only for the settings
*/
class AntennaToolsWebAPIAdapter : public FeatureWebAPIAdapter {
public:
AntennaToolsWebAPIAdapter();
virtual ~AntennaToolsWebAPIAdapter();
virtual QByteArray serialize() const { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
private:
AntennaToolsSettings m_settings;
};
#endif // INCLUDE_ANTENNATOOLS_WEBAPIADAPTER_H

View File

@ -0,0 +1,116 @@
<h1>Antenna Tools Feature Plugin</h1>
<h2>Introduction</h2>
The Antenna Tools feature has a couple of calculators to help with antenna design and tuning.
* A dipole calculator, for calculating the length of a half wave dipole for a given frequency.
* A parabolic dish calculator, for calculating focal length for a dish with a given diameter and depth, as well as corresponding gain and beamwidth for a given frequency.
Each calculator is contained within an individual tab. Settings in one tab do not effect calculations in other tabs.
<h2>Half Wave Dipole Calculator</h2>
![Half wave dipole calculator GUI](../../../doc/img/AntennaTools_plugin_dipole.png)
<h3>1: Frequency</h3>
When entering a frequency in MHz in this field, the calculator will calculate the total and element length for a half wave dipole at this frequency.
When a length is entered in (3) or (5), this field will display the corresponding resonant frequency.
<h3>2: Frequency Select</h3>
Select how the frequency is chosen:
* MHz - A frequency can be manually entered in (1) in MHz.
* Device set N - The frequency automatically tracks the centre frequency of Device Set N.
<h3>3: Dipole Total Length</h3>
This field displays the total length of a half wave dipole corresponding to the frequency entered in (1) or element length (5).
When a length is entered in this field, the calculator will calculate the corresponding frequency (1) and element length (5).
The dipole length is calculated as: l=0.5*k*c/f
<h3>4: Dipole Length Units</h3>
This field selects the units lengths are entered and displayed in. This can be:
* cm - centimetres.
* m - metres.
* feet - feet.
<h3>5: Dipole Element Length</h3>
This field displays the element length of each dipole for a half wave dipole corresponding to the frequency entered in (1) or total length (3).
When a length is entered in this field, the calculator will calculate the corresponding frequency (1) and total length (3).
<h3>6: End Effect Factor</h3>
A half wave dipole in free space with total length being half the wavelength of operation has a reactance of 43 Ohms.
To eliminate this reactance, the dipole should be shortened. The amount it needs to be shortened by depends upon the ratio of the diameter of the dipole to wavelength,
with factors ranging from 0.98 for a thin dipole (0.00001 wavelengths) to 0.94 (thickness of 0.008 wavelengths) with a commonly used value of 0.95.
The calculator doesn't use an analytical formula for this, as the reactance also depends on the enviroment (such as distance to ground), so some experimentation
is needed in finding the true value.
<h2>Parabolic Dish Calculator</h2>
![Parabolic Dish Calculator GUI](../../../doc/img/AntennaTools_plugin_dish.png)
<h3>7: Frequency</h3>
When entering a frequency in MHz in this field, the calculator will calculate the beamwidth (15) and gain (16) for a dish of the given dimensions at the entered frequency.
<h3>8: Frequency Select</h3>
Select how the frequency is chosen:
* MHz - A frequency can be manually entered in (7) in MHz.
* Device set N - The frequency automatically tracks the centre frequency of Device Set N.
<h3>9: Efficiency<h3>
Specifies the efficiency of the dish in %. When entered, the calculator will calculate the gain (16), according to the entered frequency and dimensions.
<h3>10: Diameter</h3>
When entering the diameter of the dish, the calculator will calculate the focal length (13), f/D ratio (14), beamwidth (15) and gain (16).
<h3>11: Dish Length Units</h3>
This field selects the units lengths are entered and displayed in. This can be:
* cm - centimetres.
* m - metres.
* feet - feet.
<h3>12: Depth</h3>
When entering the depth of the dish, the calculator will calculate the focal length (13) and f/D ratio (14).
<h3>13: Focal length</h3>
Displays the calculated focal length.
Focal length is calculated as: f=d^2/(16*D)
<h3>14: f/D Ratio</h3>
Displays the calculated focal length to diameter ratio.
<h3>15: Beamwidth</h3>
Displays the halfpower (-3dB) beamwidth.
Beamwidth is calculated as: 70*lambda/D.
<h3>16: Gain</h3>
Displays the calculated gain in dB.
The gain is calculated as: 10*log10(eff/100.0*(pi*D/lambda)^2)

View File

@ -41,6 +41,11 @@ public:
return (int)std::round(feetToMetres(feet));
}
static inline float metresToFeet(float metres)
{
return metres * 3.28084f;
}
static inline float nauticalMilesToMetres(float nauticalMiles)
{
return nauticalMiles * 1855.0f;

View File

@ -4430,6 +4430,11 @@ bool WebAPIRequestMapper::getFeatureSettings(
featureSettings->setAisSettings(new SWGSDRangel::SWGAISSettings());
featureSettings->getAisSettings()->fromJsonObject(settingsJsonObject);
}
else if (featureSettingsKey == "AntennaToolsSettings")
{
featureSettings->setAntennaToolsSettings(new SWGSDRangel::SWGAntennaToolsSettings());
featureSettings->getAntennaToolsSettings()->fromJsonObject(settingsJsonObject);
}
else if (featureSettingsKey == "APRSSettings")
{
featureSettings->setAprsSettings(new SWGSDRangel::SWGAPRSSettings());
@ -4701,6 +4706,7 @@ void WebAPIRequestMapper::resetFeatureSettings(SWGSDRangel::SWGFeatureSettings&
{
featureSettings.cleanup();
featureSettings.setFeatureType(nullptr);
featureSettings.setAntennaToolsSettings(nullptr);
featureSettings.setAprsSettings(nullptr);
featureSettings.setGs232ControllerSettings(nullptr);
featureSettings.setMapSettings(nullptr);

View File

@ -256,6 +256,7 @@ const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToActionsKey = {
const QMap<QString, QString> WebAPIUtils::m_featureTypeToSettingsKey = {
{"AIS", "AISSettings"},
{"AntennaTools", "AntennaToolsSettings"},
{"APRS", "APRSSettings"},
{"GS232Controller", "GS232ControllerSettings"},
{"Map", "MapSettings"},
@ -272,6 +273,7 @@ const QMap<QString, QString> WebAPIUtils::m_featureTypeToActionsKey = {
const QMap<QString, QString> WebAPIUtils::m_featureURIToSettingsKey = {
{"sdrangel.feature.ais", "AISSSettings"},
{"sdrangel.feature.antennatools", "AntennaToolsSettings"},
{"sdrangel.feature.aprs", "APRSSettings"},
{"sdrangel.feature.gs232controller", "GS232ControllerSettings"},
{"sdrangel.feature.map", "MapSettings"},

View File

@ -0,0 +1,35 @@
AntennaToolsSettings:
description: Antenna Tools
properties:
dipoleFrequencyMHz:
type: number
format: float
dipoleEndEffectFactor:
type: number
format: float
dishFrequencyMHz:
type: number
format: float
dishDiameter:
type: number
format: float
dishDepth:
type: number
format: float
dishEfficiency:
type: integer
title:
type: string
rgbColor:
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
reverseAPIChannelIndex:
type: integer

View File

@ -17,6 +17,8 @@ FeatureSettings:
$ref: "http://swgserver:8081/api/swagger/include/AFC.yaml#/AFCSettings"
AISSettings:
$ref: "http://swgserver:8081/api/swagger/include/AIS.yaml#/AISSettings"
AntennaToolsSettings:
$ref: "http://swgserver:8081/api/swagger/include/AntennaTools.yaml#/AntennaToolsSettings"
APRSSettings:
$ref: "http://swgserver:8081/api/swagger/include/APRS.yaml#/APRSSettings"
DemodAnalyzerSettings:

View File

@ -0,0 +1,388 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 6.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGAntennaToolsSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGAntennaToolsSettings::SWGAntennaToolsSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGAntennaToolsSettings::SWGAntennaToolsSettings() {
dipole_frequency_m_hz = 0.0f;
m_dipole_frequency_m_hz_isSet = false;
dipole_end_effect_factor = 0.0f;
m_dipole_end_effect_factor_isSet = false;
dish_frequency_m_hz = 0.0f;
m_dish_frequency_m_hz_isSet = false;
dish_diameter = 0.0f;
m_dish_diameter_isSet = false;
dish_depth = 0.0f;
m_dish_depth_isSet = false;
dish_efficiency = 0;
m_dish_efficiency_isSet = false;
title = nullptr;
m_title_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
SWGAntennaToolsSettings::~SWGAntennaToolsSettings() {
this->cleanup();
}
void
SWGAntennaToolsSettings::init() {
dipole_frequency_m_hz = 0.0f;
m_dipole_frequency_m_hz_isSet = false;
dipole_end_effect_factor = 0.0f;
m_dipole_end_effect_factor_isSet = false;
dish_frequency_m_hz = 0.0f;
m_dish_frequency_m_hz_isSet = false;
dish_diameter = 0.0f;
m_dish_diameter_isSet = false;
dish_depth = 0.0f;
m_dish_depth_isSet = false;
dish_efficiency = 0;
m_dish_efficiency_isSet = false;
title = new QString("");
m_title_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
void
SWGAntennaToolsSettings::cleanup() {
if(title != nullptr) {
delete title;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGAntennaToolsSettings*
SWGAntennaToolsSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGAntennaToolsSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&dipole_frequency_m_hz, pJson["dipoleFrequencyMHz"], "float", "");
::SWGSDRangel::setValue(&dipole_end_effect_factor, pJson["dipoleEndEffectFactor"], "float", "");
::SWGSDRangel::setValue(&dish_frequency_m_hz, pJson["dishFrequencyMHz"], "float", "");
::SWGSDRangel::setValue(&dish_diameter, pJson["dishDiameter"], "float", "");
::SWGSDRangel::setValue(&dish_depth, pJson["dishDepth"], "float", "");
::SWGSDRangel::setValue(&dish_efficiency, pJson["dishEfficiency"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", "");
}
QString
SWGAntennaToolsSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGAntennaToolsSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_dipole_frequency_m_hz_isSet){
obj->insert("dipoleFrequencyMHz", QJsonValue(dipole_frequency_m_hz));
}
if(m_dipole_end_effect_factor_isSet){
obj->insert("dipoleEndEffectFactor", QJsonValue(dipole_end_effect_factor));
}
if(m_dish_frequency_m_hz_isSet){
obj->insert("dishFrequencyMHz", QJsonValue(dish_frequency_m_hz));
}
if(m_dish_diameter_isSet){
obj->insert("dishDiameter", QJsonValue(dish_diameter));
}
if(m_dish_depth_isSet){
obj->insert("dishDepth", QJsonValue(dish_depth));
}
if(m_dish_efficiency_isSet){
obj->insert("dishEfficiency", QJsonValue(dish_efficiency));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
if(m_rgb_color_isSet){
obj->insert("rgbColor", QJsonValue(rgb_color));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
}
if(m_reverse_api_port_isSet){
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
}
if(m_reverse_api_device_index_isSet){
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
}
if(m_reverse_api_channel_index_isSet){
obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index));
}
return obj;
}
float
SWGAntennaToolsSettings::getDipoleFrequencyMHz() {
return dipole_frequency_m_hz;
}
void
SWGAntennaToolsSettings::setDipoleFrequencyMHz(float dipole_frequency_m_hz) {
this->dipole_frequency_m_hz = dipole_frequency_m_hz;
this->m_dipole_frequency_m_hz_isSet = true;
}
float
SWGAntennaToolsSettings::getDipoleEndEffectFactor() {
return dipole_end_effect_factor;
}
void
SWGAntennaToolsSettings::setDipoleEndEffectFactor(float dipole_end_effect_factor) {
this->dipole_end_effect_factor = dipole_end_effect_factor;
this->m_dipole_end_effect_factor_isSet = true;
}
float
SWGAntennaToolsSettings::getDishFrequencyMHz() {
return dish_frequency_m_hz;
}
void
SWGAntennaToolsSettings::setDishFrequencyMHz(float dish_frequency_m_hz) {
this->dish_frequency_m_hz = dish_frequency_m_hz;
this->m_dish_frequency_m_hz_isSet = true;
}
float
SWGAntennaToolsSettings::getDishDiameter() {
return dish_diameter;
}
void
SWGAntennaToolsSettings::setDishDiameter(float dish_diameter) {
this->dish_diameter = dish_diameter;
this->m_dish_diameter_isSet = true;
}
float
SWGAntennaToolsSettings::getDishDepth() {
return dish_depth;
}
void
SWGAntennaToolsSettings::setDishDepth(float dish_depth) {
this->dish_depth = dish_depth;
this->m_dish_depth_isSet = true;
}
qint32
SWGAntennaToolsSettings::getDishEfficiency() {
return dish_efficiency;
}
void
SWGAntennaToolsSettings::setDishEfficiency(qint32 dish_efficiency) {
this->dish_efficiency = dish_efficiency;
this->m_dish_efficiency_isSet = true;
}
QString*
SWGAntennaToolsSettings::getTitle() {
return title;
}
void
SWGAntennaToolsSettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
qint32
SWGAntennaToolsSettings::getRgbColor() {
return rgb_color;
}
void
SWGAntennaToolsSettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
qint32
SWGAntennaToolsSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGAntennaToolsSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGAntennaToolsSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGAntennaToolsSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGAntennaToolsSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGAntennaToolsSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGAntennaToolsSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGAntennaToolsSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGAntennaToolsSettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGAntennaToolsSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
bool
SWGAntennaToolsSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_dipole_frequency_m_hz_isSet){
isObjectUpdated = true; break;
}
if(m_dipole_end_effect_factor_isSet){
isObjectUpdated = true; break;
}
if(m_dish_frequency_m_hz_isSet){
isObjectUpdated = true; break;
}
if(m_dish_diameter_isSet){
isObjectUpdated = true; break;
}
if(m_dish_depth_isSet){
isObjectUpdated = true; break;
}
if(m_dish_efficiency_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}
if(m_rgb_color_isSet){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}
if(reverse_api_address && *reverse_api_address != QString("")){
isObjectUpdated = true; break;
}
if(m_reverse_api_port_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_device_index_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_channel_index_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,131 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 6.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGAntennaToolsSettings.h
*
* Antenna Tools
*/
#ifndef SWGAntennaToolsSettings_H_
#define SWGAntennaToolsSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGAntennaToolsSettings: public SWGObject {
public:
SWGAntennaToolsSettings();
SWGAntennaToolsSettings(QString* json);
virtual ~SWGAntennaToolsSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGAntennaToolsSettings* fromJson(QString &jsonString) override;
float getDipoleFrequencyMHz();
void setDipoleFrequencyMHz(float dipole_frequency_m_hz);
float getDipoleEndEffectFactor();
void setDipoleEndEffectFactor(float dipole_end_effect_factor);
float getDishFrequencyMHz();
void setDishFrequencyMHz(float dish_frequency_m_hz);
float getDishDiameter();
void setDishDiameter(float dish_diameter);
float getDishDepth();
void setDishDepth(float dish_depth);
qint32 getDishEfficiency();
void setDishEfficiency(qint32 dish_efficiency);
QString* getTitle();
void setTitle(QString* title);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
QString* getReverseApiAddress();
void setReverseApiAddress(QString* reverse_api_address);
qint32 getReverseApiPort();
void setReverseApiPort(qint32 reverse_api_port);
qint32 getReverseApiDeviceIndex();
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
qint32 getReverseApiChannelIndex();
void setReverseApiChannelIndex(qint32 reverse_api_channel_index);
virtual bool isSet() override;
private:
float dipole_frequency_m_hz;
bool m_dipole_frequency_m_hz_isSet;
float dipole_end_effect_factor;
bool m_dipole_end_effect_factor_isSet;
float dish_frequency_m_hz;
bool m_dish_frequency_m_hz_isSet;
float dish_diameter;
bool m_dish_diameter_isSet;
float dish_depth;
bool m_dish_depth_isSet;
qint32 dish_efficiency;
bool m_dish_efficiency_isSet;
QString* title;
bool m_title_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;
QString* reverse_api_address;
bool m_reverse_api_address_isSet;
qint32 reverse_api_port;
bool m_reverse_api_port_isSet;
qint32 reverse_api_device_index;
bool m_reverse_api_device_index_isSet;
qint32 reverse_api_channel_index;
bool m_reverse_api_channel_index_isSet;
};
}
#endif /* SWGAntennaToolsSettings_H_ */

View File

@ -38,6 +38,8 @@ SWGFeatureSettings::SWGFeatureSettings() {
m_afc_settings_isSet = false;
ais_settings = nullptr;
m_ais_settings_isSet = false;
antenna_tools_settings = nullptr;
m_antenna_tools_settings_isSet = false;
aprs_settings = nullptr;
m_aprs_settings_isSet = false;
demod_analyzer_settings = nullptr;
@ -76,6 +78,8 @@ SWGFeatureSettings::init() {
m_afc_settings_isSet = false;
ais_settings = new SWGAISSettings();
m_ais_settings_isSet = false;
antenna_tools_settings = new SWGAntennaToolsSettings();
m_antenna_tools_settings_isSet = false;
aprs_settings = new SWGAPRSSettings();
m_aprs_settings_isSet = false;
demod_analyzer_settings = new SWGDemodAnalyzerSettings();
@ -111,6 +115,9 @@ SWGFeatureSettings::cleanup() {
if(ais_settings != nullptr) {
delete ais_settings;
}
if(antenna_tools_settings != nullptr) {
delete antenna_tools_settings;
}
if(aprs_settings != nullptr) {
delete aprs_settings;
}
@ -164,6 +171,8 @@ SWGFeatureSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&ais_settings, pJson["AISSettings"], "SWGAISSettings", "SWGAISSettings");
::SWGSDRangel::setValue(&antenna_tools_settings, pJson["AntennaToolsSettings"], "SWGAntennaToolsSettings", "SWGAntennaToolsSettings");
::SWGSDRangel::setValue(&aprs_settings, pJson["APRSSettings"], "SWGAPRSSettings", "SWGAPRSSettings");
::SWGSDRangel::setValue(&demod_analyzer_settings, pJson["DemodAnalyzerSettings"], "SWGDemodAnalyzerSettings", "SWGDemodAnalyzerSettings");
@ -215,6 +224,9 @@ SWGFeatureSettings::asJsonObject() {
if((ais_settings != nullptr) && (ais_settings->isSet())){
toJsonValue(QString("AISSettings"), ais_settings, obj, QString("SWGAISSettings"));
}
if((antenna_tools_settings != nullptr) && (antenna_tools_settings->isSet())){
toJsonValue(QString("AntennaToolsSettings"), antenna_tools_settings, obj, QString("SWGAntennaToolsSettings"));
}
if((aprs_settings != nullptr) && (aprs_settings->isSet())){
toJsonValue(QString("APRSSettings"), aprs_settings, obj, QString("SWGAPRSSettings"));
}
@ -299,6 +311,16 @@ SWGFeatureSettings::setAisSettings(SWGAISSettings* ais_settings) {
this->m_ais_settings_isSet = true;
}
SWGAntennaToolsSettings*
SWGFeatureSettings::getAntennaToolsSettings() {
return antenna_tools_settings;
}
void
SWGFeatureSettings::setAntennaToolsSettings(SWGAntennaToolsSettings* antenna_tools_settings) {
this->antenna_tools_settings = antenna_tools_settings;
this->m_antenna_tools_settings_isSet = true;
}
SWGAPRSSettings*
SWGFeatureSettings::getAprsSettings() {
return aprs_settings;
@ -419,6 +441,9 @@ SWGFeatureSettings::isSet(){
if(ais_settings && ais_settings->isSet()){
isObjectUpdated = true; break;
}
if(antenna_tools_settings && antenna_tools_settings->isSet()){
isObjectUpdated = true; break;
}
if(aprs_settings && aprs_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -25,6 +25,7 @@
#include "SWGAFCSettings.h"
#include "SWGAISSettings.h"
#include "SWGAPRSSettings.h"
#include "SWGAntennaToolsSettings.h"
#include "SWGDemodAnalyzerSettings.h"
#include "SWGGS232ControllerSettings.h"
#include "SWGMapSettings.h"
@ -69,6 +70,9 @@ public:
SWGAISSettings* getAisSettings();
void setAisSettings(SWGAISSettings* ais_settings);
SWGAntennaToolsSettings* getAntennaToolsSettings();
void setAntennaToolsSettings(SWGAntennaToolsSettings* antenna_tools_settings);
SWGAPRSSettings* getAprsSettings();
void setAprsSettings(SWGAPRSSettings* aprs_settings);
@ -118,6 +122,9 @@ private:
SWGAISSettings* ais_settings;
bool m_ais_settings_isSet;
SWGAntennaToolsSettings* antenna_tools_settings;
bool m_antenna_tools_settings_isSet;
SWGAPRSSettings* aprs_settings;
bool m_aprs_settings_isSet;

View File

@ -44,6 +44,7 @@
#include "SWGAirspyHFSettings.h"
#include "SWGAirspyReport.h"
#include "SWGAirspySettings.h"
#include "SWGAntennaToolsSettings.h"
#include "SWGArgInfo.h"
#include "SWGArgValue.h"
#include "SWGAudioDevices.h"
@ -363,6 +364,9 @@ namespace SWGSDRangel {
if(QString("SWGAirspySettings").compare(type) == 0) {
return new SWGAirspySettings();
}
if(QString("SWGAntennaToolsSettings").compare(type) == 0) {
return new SWGAntennaToolsSettings();
}
if(QString("SWGArgInfo").compare(type) == 0) {
return new SWGArgInfo();
}