diff --git a/plugins/feature/CMakeLists.txt b/plugins/feature/CMakeLists.txt index 6bc185fbf..b809b08e4 100644 --- a/plugins/feature/CMakeLists.txt +++ b/plugins/feature/CMakeLists.txt @@ -13,6 +13,7 @@ endif() add_subdirectory(afc) add_subdirectory(ais) +add_subdirectory(antennatools) add_subdirectory(aprs) add_subdirectory(demodanalyzer) add_subdirectory(pertester) diff --git a/plugins/feature/antennatools/CMakeLists.txt b/plugins/feature/antennatools/CMakeLists.txt new file mode 100644 index 000000000..0b8aed990 --- /dev/null +++ b/plugins/feature/antennatools/CMakeLists.txt @@ -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}) diff --git a/plugins/feature/antennatools/antennatools.cpp b/plugins/feature/antennatools/antennatools.cpp new file mode 100644 index 000000000..c760221cd --- /dev/null +++ b/plugins/feature/antennatools/antennatools.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#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 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& 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(); +} diff --git a/plugins/feature/antennatools/antennatools.h b/plugins/feature/antennatools/antennatools.h new file mode 100644 index 000000000..e4f65ac40 --- /dev/null +++ b/plugins/feature/antennatools/antennatools.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_ANTENNATOOLS_H_ +#define INCLUDE_FEATURE_ANTENNATOOLS_H_ + +#include +#include +#include +#include + +#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& featureSettingsKeys, const AntennaToolsSettings& settings, bool force); + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // INCLUDE_FEATURE_ANTENNATOOLS_H_ diff --git a/plugins/feature/antennatools/antennatools.qrc b/plugins/feature/antennatools/antennatools.qrc new file mode 100644 index 000000000..50cb4b409 --- /dev/null +++ b/plugins/feature/antennatools/antennatools.qrc @@ -0,0 +1,6 @@ + + + antennatools/dipole.png + antennatools/dish.png + + diff --git a/plugins/feature/antennatools/antennatools/dipole.png b/plugins/feature/antennatools/antennatools/dipole.png new file mode 100644 index 000000000..3fc1f0f1d Binary files /dev/null and b/plugins/feature/antennatools/antennatools/dipole.png differ diff --git a/plugins/feature/antennatools/antennatools/dish.png b/plugins/feature/antennatools/antennatools/dish.png new file mode 100644 index 000000000..52a91775d Binary files /dev/null and b/plugins/feature/antennatools/antennatools/dish.png differ diff --git a/plugins/feature/antennatools/antennatoolsgui.cpp b/plugins/feature/antennatools/antennatoolsgui.cpp new file mode 100644 index 000000000..9f6cf8ee5 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolsgui.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#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(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 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 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; + } +} diff --git a/plugins/feature/antennatools/antennatoolsgui.h b/plugins/feature/antennatools/antennatoolsgui.h new file mode 100644 index 000000000..e4a85f0b5 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolsgui.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_ANTENNATOOLSGUI_H_ +#define INCLUDE_FEATURE_ANTENNATOOLSGUI_H_ + +#include +#include + +#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_ diff --git a/plugins/feature/antennatools/antennatoolsgui.ui b/plugins/feature/antennatools/antennatoolsgui.ui new file mode 100644 index 000000000..136767aae --- /dev/null +++ b/plugins/feature/antennatools/antennatoolsgui.ui @@ -0,0 +1,497 @@ + + + AntennaToolsGUI + + + + 0 + 0 + 377 + 461 + + + + + 0 + 0 + + + + + 360 + 0 + + + + + Liberation Sans + 9 + + + + Qt::StrongFocus + + + Antenna Tools + + + AntennaTools + + + + + 16 + 19 + 351 + 431 + + + + + 0 + 0 + + + + Calculators + + + 0 + + + + Dipole + + + + + + + 94 + 0 + + + + + MHz + + + + + + + + Frequency + + + + + + + Total length of dipole + + + 2000000000.000000000000000 + + + 100.000000000000000 + + + + + + + Units for lengths + + + + cm + + + + + m + + + + + feet + + + + + + + + End effect factor to correct for reactance + + + 0.900000000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 0.950000000000000 + + + + + + + Dipole element length + + + 2000000000.000000000000000 + + + + + + + Frequency to calculate the length for + + + 3 + + + 100000.000000000000000 + + + 2400.000000000000000 + + + + + + + End effect factor + + + + + + + Element length + + + + + + + Total length + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + :/antennatools/antennatools/dipole.png + + + Qt::AlignCenter + + + + + + + + Dish + + + + + + Beamwidth (°) + + + + + + + Focal length to diameter ratio + + + true + + + 1.000000000000000 + + + + + + + Diameter + + + + + + + + + + :/antennatools/antennatools/dish.png + + + Qt::AlignCenter + + + + + + + f/D + + + + + + + + 0 + 0 + + + + + 94 + 0 + + + + + + + + MHz + + + + + + + + Dish gain + + + true + + + 1000.000000000000000 + + + + + + + Dish efficiency in percent + + + 100 + + + + + + + Depth + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Units for lengths + + + + cm + + + + + m + + + + + feet + + + + + + + + Gain (dB) + + + + + + + Halfpower (-3dB) beamwidth in degrees + + + true + + + 360.000000000000000 + + + + + + + Efficiency (%) + + + + + + + Depth of the dish + + + 1000.000000000000000 + + + + + + + Frequency of operation + + + 3 + + + 20000.000000000000000 + + + 2400.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Frequency + + + + + + + Diameter of the dish + + + 1000.000000000000000 + + + 100.000000000000000 + + + + + + + Focal length + + + + + + + Focal length + + + true + + + 1000.000000000000000 + + + + + + + + + + RollupWidget + QWidget +
gui/rollupwidget.h
+ 1 +
+
+ + tabWidget + dipoleFrequency + dipoleFrequencySelect + dipoleLength + dipoleLengthUnits + dipoleElementLength + dipoleEndEffectFactor + dishFrequency + dishFrequencySelect + dishDiameter + dishLengthUnits + dishDepth + dishFD + dishBeamwidth + dishGain + + + + + + +
diff --git a/plugins/feature/antennatools/antennatoolsplugin.cpp b/plugins/feature/antennatools/antennatoolsplugin.cpp new file mode 100644 index 000000000..8e4f199eb --- /dev/null +++ b/plugins/feature/antennatools/antennatoolsplugin.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + + +#include +#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(); +} diff --git a/plugins/feature/antennatools/antennatoolsplugin.h b/plugins/feature/antennatools/antennatoolsplugin.h new file mode 100644 index 000000000..eb6f2e643 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolsplugin.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_ANTENNATOOLSPLUGIN_H +#define INCLUDE_FEATURE_ANTENNATOOLSPLUGIN_H + +#include +#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 diff --git a/plugins/feature/antennatools/antennatoolssettings.cpp b/plugins/feature/antennatools/antennatoolssettings.cpp new file mode 100644 index 000000000..4afadb5b6 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolssettings.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#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; + } +} diff --git a/plugins/feature/antennatools/antennatoolssettings.h b/plugins/feature/antennatools/antennatoolssettings.h new file mode 100644 index 000000000..4df71e3c9 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolssettings.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_ANTENNATOOLSSETTINGS_H_ +#define INCLUDE_FEATURE_ANTENNATOOLSSETTINGS_H_ + +#include +#include + +#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_ diff --git a/plugins/feature/antennatools/antennatoolswebapiadapter.cpp b/plugins/feature/antennatools/antennatoolswebapiadapter.cpp new file mode 100644 index 000000000..49d4174f3 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolswebapiadapter.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#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; +} diff --git a/plugins/feature/antennatools/antennatoolswebapiadapter.h b/plugins/feature/antennatools/antennatoolswebapiadapter.h new file mode 100644 index 000000000..4b452d149 --- /dev/null +++ b/plugins/feature/antennatools/antennatoolswebapiadapter.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#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 diff --git a/plugins/feature/antennatools/readme.md b/plugins/feature/antennatools/readme.md new file mode 100644 index 000000000..4bcc99ee0 --- /dev/null +++ b/plugins/feature/antennatools/readme.md @@ -0,0 +1,116 @@ +

Antenna Tools Feature Plugin

+ +

Introduction

+ +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. + +

Half Wave Dipole Calculator

+ +![Half wave dipole calculator GUI](../../../doc/img/AntennaTools_plugin_dipole.png) + +

1: Frequency

+ +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. + +

2: Frequency Select

+ +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. + +

3: Dipole Total Length

+ +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 + +

4: Dipole Length Units

+ +This field selects the units lengths are entered and displayed in. This can be: + +* cm - centimetres. +* m - metres. +* feet - feet. + +

5: Dipole Element Length

+ +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). + +

6: End Effect Factor

+ +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. + +

Parabolic Dish Calculator

+ +![Parabolic Dish Calculator GUI](../../../doc/img/AntennaTools_plugin_dish.png) + +

7: Frequency

+ +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. + +

8: Frequency Select

+ +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. + +

9: Efficiency

+ +Specifies the efficiency of the dish in %. When entered, the calculator will calculate the gain (16), according to the entered frequency and dimensions. + +

10: Diameter

+ +When entering the diameter of the dish, the calculator will calculate the focal length (13), f/D ratio (14), beamwidth (15) and gain (16). + +

11: Dish Length Units

+ +This field selects the units lengths are entered and displayed in. This can be: + +* cm - centimetres. +* m - metres. +* feet - feet. + +

12: Depth

+ +When entering the depth of the dish, the calculator will calculate the focal length (13) and f/D ratio (14). + +

13: Focal length

+ +Displays the calculated focal length. + +Focal length is calculated as: f=d^2/(16*D) + +

14: f/D Ratio

+ +Displays the calculated focal length to diameter ratio. + +

15: Beamwidth

+ +Displays the halfpower (-3dB) beamwidth. + +Beamwidth is calculated as: 70*lambda/D. + +

16: Gain

+ +Displays the calculated gain in dB. + +The gain is calculated as: 10*log10(eff/100.0*(pi*D/lambda)^2) diff --git a/sdrbase/util/units.h b/sdrbase/util/units.h index 0d6559870..50af66c51 100644 --- a/sdrbase/util/units.h +++ b/sdrbase/util/units.h @@ -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; diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index fc622b828..b5ee0c675 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -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); diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index 487670022..4059d7115 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -256,6 +256,7 @@ const QMap WebAPIUtils::m_mimoDeviceHwIdToActionsKey = { const QMap WebAPIUtils::m_featureTypeToSettingsKey = { {"AIS", "AISSettings"}, + {"AntennaTools", "AntennaToolsSettings"}, {"APRS", "APRSSettings"}, {"GS232Controller", "GS232ControllerSettings"}, {"Map", "MapSettings"}, @@ -272,6 +273,7 @@ const QMap WebAPIUtils::m_featureTypeToActionsKey = { const QMap WebAPIUtils::m_featureURIToSettingsKey = { {"sdrangel.feature.ais", "AISSSettings"}, + {"sdrangel.feature.antennatools", "AntennaToolsSettings"}, {"sdrangel.feature.aprs", "APRSSettings"}, {"sdrangel.feature.gs232controller", "GS232ControllerSettings"}, {"sdrangel.feature.map", "MapSettings"}, diff --git a/swagger/sdrangel/api/swagger/include/AntennaTools.yaml b/swagger/sdrangel/api/swagger/include/AntennaTools.yaml new file mode 100644 index 000000000..ba5e62d3d --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/AntennaTools.yaml @@ -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 diff --git a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml index 5ac4dc6da..d3004e06b 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml @@ -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: diff --git a/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.cpp new file mode 100644 index 000000000..a5e7df196 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.cpp @@ -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 +#include +#include +#include + +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; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.h b/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.h new file mode 100644 index 000000000..84dcab495 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAntennaToolsSettings.h @@ -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 + + +#include + +#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_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp index 8934debaa..fb4a8d25b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp @@ -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; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h index e6f8b95f5..177080513 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h @@ -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; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index c2be13c2c..22dadfcb3 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -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(); }