From 3e004a257b122cde32b92c102068025733fd6186 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Fri, 16 Oct 2020 19:18:54 +0200 Subject: [PATCH 01/27] AFC plguin: REST API: sources --- swagger/sdrangel/api/swagger/include/AFC.yaml | 50 +++++++++++++++++++ .../api/swagger/include/FeatureActions.yaml | 2 + .../api/swagger/include/FeatureReport.yaml | 2 + .../api/swagger/include/FeatureSettings.yaml | 2 + 4 files changed, 56 insertions(+) create mode 100644 swagger/sdrangel/api/swagger/include/AFC.yaml diff --git a/swagger/sdrangel/api/swagger/include/AFC.yaml b/swagger/sdrangel/api/swagger/include/AFC.yaml new file mode 100644 index 000000000..4397ab890 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/AFC.yaml @@ -0,0 +1,50 @@ +AFCSettings: + description: "AFC settings" + properties: + title: + type: string + rgbColor: + type: integer + rxDeviceSetIndex: + description: index of the Rx device set to connect the Rx side to + type: integer + txDeviceSetIndex: + description: index of the Tx device set to connect the Tx side to + type: integer + rx2TxDelayMs: + description: Delay in milliseconds from Rx off to Tx on + type: integer + tx2RxDelayMs: + description: Delay in milliseconds from Tx off to Rx on + 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 + +AFCReport: + description: "AFC report" + properties: + ptt: + type: integer + description: > + AFC status + * 0 - released + * 1 - engaged + +AFCActions: + description: "AFC actions" + properties: + ptt: + type: integer + description: > + AFC action + * 0 - release + * 1 - engage diff --git a/swagger/sdrangel/api/swagger/include/FeatureActions.yaml b/swagger/sdrangel/api/swagger/include/FeatureActions.yaml index 148f90b6d..5739ae33e 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureActions.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureActions.yaml @@ -13,5 +13,7 @@ FeatureActions: originatorFeatureIndex: description: Optional for reverse API. This is the feature index from where the message comes from. type: integer + AFCActions: + $ref: "http://swgserver:8081/api/swagger/include/AFC.yaml#/AFCActions" SimplePTTActions: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTActions" diff --git a/swagger/sdrangel/api/swagger/include/FeatureReport.yaml b/swagger/sdrangel/api/swagger/include/FeatureReport.yaml index 4cfc15ac5..de58bdda8 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureReport.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureReport.yaml @@ -7,5 +7,7 @@ FeatureReport: featureType: description: Feature type code type: string + AFCReport: + $ref: "http://swgserver:8081/api/swagger/include/AFC.yaml#/AFCReport" SimplePTTReport: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTReport" diff --git a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml index d673f7e0d..c4bb5b710 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml @@ -13,6 +13,8 @@ FeatureSettings: originatorFeatureIndex: description: Optional for reverse API. This is the feature index from where the message comes from. type: integer + AFCSettings: + $ref: "http://swgserver:8081/api/swagger/include/AFC.yaml#/AFCSettings" SimplePTTSettings: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTSettings" RigCtlServerSettings: From 0cd512ce4a79f03da62970b625fe1d882d218e58 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Fri, 16 Oct 2020 19:20:55 +0200 Subject: [PATCH 02/27] AFC plugin: brute force copy from Simple PTT plugin --- plugins/feature/CMakeLists.txt | 1 + plugins/feature/afc/CMakeLists.txt | 58 +++ plugins/feature/afc/afc.cpp | 427 +++++++++++++++++++++++ plugins/feature/afc/afc.h | 168 +++++++++ plugins/feature/afc/afcgui.cpp | 397 +++++++++++++++++++++ plugins/feature/afc/afcgui.h | 88 +++++ plugins/feature/afc/afcgui.ui | 324 +++++++++++++++++ plugins/feature/afc/afcplugin.cpp | 80 +++++ plugins/feature/afc/afcplugin.h | 48 +++ plugins/feature/afc/afcreport.cpp | 26 ++ plugins/feature/afc/afcreport.h | 55 +++ plugins/feature/afc/afcsettings.cpp | 109 ++++++ plugins/feature/afc/afcsettings.h | 46 +++ plugins/feature/afc/afcwebapiadapter.cpp | 50 +++ plugins/feature/afc/afcwebapiadapter.h | 49 +++ plugins/feature/afc/afcworker.cpp | 210 +++++++++++ plugins/feature/afc/afcworker.h | 106 ++++++ plugins/feature/afc/readme.md | 45 +++ 18 files changed, 2287 insertions(+) create mode 100644 plugins/feature/afc/CMakeLists.txt create mode 100644 plugins/feature/afc/afc.cpp create mode 100644 plugins/feature/afc/afc.h create mode 100644 plugins/feature/afc/afcgui.cpp create mode 100644 plugins/feature/afc/afcgui.h create mode 100644 plugins/feature/afc/afcgui.ui create mode 100644 plugins/feature/afc/afcplugin.cpp create mode 100644 plugins/feature/afc/afcplugin.h create mode 100644 plugins/feature/afc/afcreport.cpp create mode 100644 plugins/feature/afc/afcreport.h create mode 100644 plugins/feature/afc/afcsettings.cpp create mode 100644 plugins/feature/afc/afcsettings.h create mode 100644 plugins/feature/afc/afcwebapiadapter.cpp create mode 100644 plugins/feature/afc/afcwebapiadapter.h create mode 100644 plugins/feature/afc/afcworker.cpp create mode 100644 plugins/feature/afc/afcworker.h create mode 100644 plugins/feature/afc/readme.md diff --git a/plugins/feature/CMakeLists.txt b/plugins/feature/CMakeLists.txt index 58a75ed42..ebb46fb9c 100644 --- a/plugins/feature/CMakeLists.txt +++ b/plugins/feature/CMakeLists.txt @@ -1,4 +1,5 @@ project(feature) +add_subdirectory(afc) add_subdirectory(rigctlserver) add_subdirectory(simpleptt) diff --git a/plugins/feature/afc/CMakeLists.txt b/plugins/feature/afc/CMakeLists.txt new file mode 100644 index 000000000..2f240e401 --- /dev/null +++ b/plugins/feature/afc/CMakeLists.txt @@ -0,0 +1,58 @@ +project(afc) + +set(afc_SOURCES + afc.cpp + afcsettings.cpp + afcplugin.cpp + afcworker.cpp + afcreport.cpp + afcwebapiadapter.cpp +) + +set(afc_HEADERS + afc.h + afcsettings.h + afcplugin.h + afcworker.h + afcreport.h + afcwebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client +) + +if(NOT SERVER_MODE) + set(afc_SOURCES + ${afc_SOURCES} + afcgui.cpp + afcgui.ui + ) + set(afc_HEADERS + ${afc_HEADERS} + afcgui.h + ) + + set(TARGET_NAME featureafc) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME featureafcsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${afc_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/afc/afc.cpp b/plugins/feature/afc/afc.cpp new file mode 100644 index 000000000..5f33e1a76 --- /dev/null +++ b/plugins/feature/afc/afc.cpp @@ -0,0 +1,427 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "SWGAFCReport.h" +#include "SWGDeviceState.h" + +#include "dsp/dspengine.h" + +#include "afcworker.h" +#include "afc.h" + +MESSAGE_CLASS_DEFINITION(AFC::MsgConfigureAFC, Message) +MESSAGE_CLASS_DEFINITION(AFC::MsgPTT, Message) +MESSAGE_CLASS_DEFINITION(AFC::MsgStartStop, Message) + +const QString AFC::m_featureIdURI = "sdrangel.feature.afc"; +const QString AFC::m_featureId = "AFC"; + +AFC::AFC(WebAPIAdapterInterface *webAPIAdapterInterface) : + Feature(m_featureIdURI, webAPIAdapterInterface), + m_ptt(false) +{ + setObjectName(m_featureId); + m_worker = new AFCWorker(webAPIAdapterInterface); + m_state = StIdle; + m_errorMessage = "AFC error"; +} + +AFC::~AFC() +{ + if (m_worker->isRunning()) { + stop(); + } + + delete m_worker; +} + +void AFC::start() +{ + qDebug("AFC::start"); + + m_worker->reset(); + m_worker->setMessageQueueToGUI(getMessageQueueToGUI()); + bool ok = m_worker->startWork(); + m_state = ok ? StRunning : StError; + m_thread.start(); + + AFCWorker::MsgConfigureAFCWorker *msg = AFCWorker::MsgConfigureAFCWorker::create(m_settings, true); + m_worker->getInputMessageQueue()->push(msg); +} + +void AFC::stop() +{ + qDebug("AFC::stop"); + m_worker->stopWork(); + m_state = StIdle; + m_thread.quit(); + m_thread.wait(); +} + +bool AFC::handleMessage(const Message& cmd) +{ + if (MsgConfigureAFC::match(cmd)) + { + MsgConfigureAFC& cfg = (MsgConfigureAFC&) cmd; + qDebug() << "AFC::handleMessage: MsgConfigureAFC"; + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (MsgPTT::match(cmd)) + { + MsgPTT& cfg = (MsgPTT&) cmd; + m_ptt = cfg.getTx(); + qDebug() << "AFC::handleMessage: MsgPTT: tx:" << m_ptt; + + AFCWorker::MsgPTT *msg = AFCWorker::MsgPTT::create(m_ptt); + m_worker->getInputMessageQueue()->push(msg); + + return true; + } + else if (MsgStartStop::match(cmd)) + { + MsgStartStop& cfg = (MsgStartStop&) cmd; + qDebug() << "AFC::handleMessage: MsgStartStop: start:" << cfg.getStartStop(); + + if (cfg.getStartStop()) { + start(); + } else { + stop(); + } + + return true; + } + else + { + return false; + } +} + +QByteArray AFC::serialize() const +{ + return m_settings.serialize(); +} + +bool AFC::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + MsgConfigureAFC *msg = MsgConfigureAFC::create(m_settings, true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureAFC *msg = MsgConfigureAFC::create(m_settings, true); + m_inputMessageQueue.push(msg); + return false; + } +} + +void AFC::applySettings(const AFCSettings& settings, bool force) +{ + qDebug() << "AFC::applySettings:" + << " m_title: " << settings.m_title + << " m_rgbColor: " << settings.m_rgbColor + << " m_rxDeviceSetIndex: " << settings.m_rxDeviceSetIndex + << " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex + << " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs + << " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs + << " 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 ((m_settings.m_rxDeviceSetIndex != settings.m_rxDeviceSetIndex) || force) { + reverseAPIKeys.append("rxDeviceSetIndex"); + } + if ((m_settings.m_txDeviceSetIndex != settings.m_txDeviceSetIndex) || force) { + reverseAPIKeys.append("txDeviceSetIndex"); + } + if ((m_settings.m_rx2TxDelayMs != settings.m_rx2TxDelayMs) || force) { + reverseAPIKeys.append("rx2TxDelayMs"); + } + if ((m_settings.m_tx2RxDelayMs != settings.m_tx2RxDelayMs) || force) { + reverseAPIKeys.append("tx2RxDelayMs"); + } + + AFCWorker::MsgConfigureAFCWorker *msg = AFCWorker::MsgConfigureAFCWorker::create( + settings, force + ); + m_worker->getInputMessageQueue()->push(msg); + + 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 AFC::webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + getFeatureStateStr(*response.getState()); + MsgStartStop *msg = MsgStartStop::create(run); + getInputMessageQueue()->push(msg); + return 202; +} + +int AFC::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAfcSettings(new SWGSDRangel::SWGAFCSettings()); + response.getAfcSettings()->init(); + webapiFormatFeatureSettings(response, m_settings); + return 200; +} + +int AFC::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + AFCSettings settings = m_settings; + webapiUpdateFeatureSettings(settings, featureSettingsKeys, response); + + MsgConfigureAFC *msg = MsgConfigureAFC::create(settings, force); + m_inputMessageQueue.push(msg); + + qDebug("AFC::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue); + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureAFC *msgToGUI = MsgConfigureAFC::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatFeatureSettings(response, settings); + + return 200; +} + +int AFC::webapiReportGet( + SWGSDRangel::SWGFeatureReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAfcReport(new SWGSDRangel::SWGAFCReport()); + response.getAfcReport()->init(); + webapiFormatFeatureReport(response); + return 200; +} + +int AFC::webapiActionsPost( + const QStringList& featureActionsKeys, + SWGSDRangel::SWGFeatureActions& query, + QString& errorMessage) +{ + SWGSDRangel::SWGAFCActions *swgAFCActions = query.getAfcActions(); + + if (swgAFCActions) + { + if (featureActionsKeys.contains("ptt")) + { + bool ptt = swgAFCActions->getPtt() != 0; + + MsgPTT *msg = MsgPTT::create(ptt); + getInputMessageQueue()->push(msg); + + if (getMessageQueueToGUI()) + { + MsgPTT *msgToGUI = MsgPTT::create(ptt); + getMessageQueueToGUI()->push(msgToGUI); + } + } + + return 202; + } + else + { + errorMessage = "Missing AFCActions in query"; + return 400; + } +} + +void AFC::webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const AFCSettings& settings) +{ + if (response.getAfcSettings()->getTitle()) { + *response.getAfcSettings()->getTitle() = settings.m_title; + } else { + response.getAfcSettings()->setTitle(new QString(settings.m_title)); + } + + response.getAfcSettings()->setRgbColor(settings.m_rgbColor); + response.getAfcSettings()->setRxDeviceSetIndex(settings.m_rxDeviceSetIndex); + response.getAfcSettings()->setTxDeviceSetIndex(settings.m_txDeviceSetIndex); + response.getAfcSettings()->setRx2TxDelayMs(settings.m_rx2TxDelayMs); + response.getAfcSettings()->setTx2RxDelayMs(settings.m_tx2RxDelayMs); + + response.getAfcSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getAfcSettings()->getReverseApiAddress()) { + *response.getAfcSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getAfcSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getAfcSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getAfcSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIFeatureSetIndex); + response.getAfcSettings()->setReverseApiChannelIndex(settings.m_reverseAPIFeatureIndex); +} + +void AFC::webapiUpdateFeatureSettings( + AFCSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response) +{ + if (featureSettingsKeys.contains("title")) { + settings.m_title = *response.getAfcSettings()->getTitle(); + } + if (featureSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getAfcSettings()->getRgbColor(); + } + if (featureSettingsKeys.contains("rxDeviceSetIndex")) { + settings.m_rxDeviceSetIndex = response.getAfcSettings()->getRxDeviceSetIndex(); + } + if (featureSettingsKeys.contains("txDeviceSetIndex")) { + settings.m_txDeviceSetIndex = response.getAfcSettings()->getTxDeviceSetIndex(); + } + if (featureSettingsKeys.contains("rx2TxDelayMs")) { + settings.m_rx2TxDelayMs = response.getAfcSettings()->getRx2TxDelayMs(); + } + if (featureSettingsKeys.contains("tx2RxDelayMs")) { + settings.m_tx2RxDelayMs = response.getAfcSettings()->getTx2RxDelayMs(); + } + if (featureSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getAfcSettings()->getUseReverseApi() != 0; + } + if (featureSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getAfcSettings()->getReverseApiAddress(); + } + if (featureSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getAfcSettings()->getReverseApiPort(); + } + if (featureSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIFeatureSetIndex = response.getAfcSettings()->getReverseApiDeviceIndex(); + } + if (featureSettingsKeys.contains("reverseAPIChannelIndex")) { + settings.m_reverseAPIFeatureIndex = response.getAfcSettings()->getReverseApiChannelIndex(); + } +} + +void AFC::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response) +{ + response.getAfcReport()->setPtt(m_ptt ? 1 : 0); +} + +void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AFCSettings& settings, bool force) +{ + SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = new SWGSDRangel::SWGFeatureSettings(); + // swgFeatureSettings->setOriginatorFeatureIndex(getIndexInDeviceSet()); + // swgFeatureSettings->setOriginatorFeatureSetIndex(getDeviceSetIndex()); + swgFeatureSettings->setFeatureType(new QString("AFC")); + swgFeatureSettings->setAfcSettings(new SWGSDRangel::SWGAFCSettings()); + SWGSDRangel::SWGAFCSettings *swgAFCSettings = swgFeatureSettings->getAfcSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("title") || force) { + swgAFCSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgAFCSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("rxDeviceSetIndex") || force) { + swgAFCSettings->setRxDeviceSetIndex(settings.m_rxDeviceSetIndex); + } + if (channelSettingsKeys.contains("txDeviceSetIndex") || force) { + swgAFCSettings->setTxDeviceSetIndex(settings.m_txDeviceSetIndex); + } + if (channelSettingsKeys.contains("rx2TxDelayMs") || force) { + swgAFCSettings->setRx2TxDelayMs(settings.m_rx2TxDelayMs); + } + if (channelSettingsKeys.contains("tx2RxDelayMs") || force) { + swgAFCSettings->setTx2RxDelayMs(settings.m_tx2RxDelayMs); + } + + 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 AFC::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "AFC::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("AFC::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} diff --git a/plugins/feature/afc/afc.h b/plugins/feature/afc/afc.h new file mode 100644 index 000000000..9cdb1afb4 --- /dev/null +++ b/plugins/feature/afc/afc.h @@ -0,0 +1,168 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFC_H_ +#define INCLUDE_FEATURE_AFC_H_ + +#include <QThread> +#include <QNetworkRequest> + +#include "feature/feature.h" +#include "util/message.h" + +#include "afcsettings.h" + +class WebAPIAdapterInterface; +class AFCWorker; +class QNetworkAccessManager; +class QNetworkReply; + +namespace SWGSDRangel { + class SWGDeviceState; +} + +class AFC : public Feature +{ + Q_OBJECT +public: + class MsgConfigureAFC : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const AFCSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureAFC* create(const AFCSettings& settings, bool force) { + return new MsgConfigureAFC(settings, force); + } + + private: + AFCSettings m_settings; + bool m_force; + + MsgConfigureAFC(const AFCSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgPTT : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getTx() const { return m_tx; } + + static MsgPTT* create(bool tx) { + return new MsgPTT(tx); + } + + private: + bool m_tx; + + MsgPTT(bool tx) : + Message(), + m_tx(tx) + { } + }; + + class MsgStartStop : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getStartStop() const { return m_startStop; } + + static MsgStartStop* create(bool startStop) { + return new MsgStartStop(startStop); + } + + protected: + bool m_startStop; + + MsgStartStop(bool startStop) : + Message(), + m_startStop(startStop) + { } + }; + + AFC(WebAPIAdapterInterface *webAPIAdapterInterface); + virtual ~AFC(); + virtual void destroy() { delete this; } + virtual bool handleMessage(const Message& cmd); + + virtual const QString& getURI() const { return m_featureIdURI; } + virtual void getIdentifier(QString& id) const { id = m_featureId; } + virtual void getTitle(QString& title) const { title = m_settings.m_title; } + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGFeatureReport& response, + QString& errorMessage); + + virtual int webapiActionsPost( + const QStringList& featureActionsKeys, + SWGSDRangel::SWGFeatureActions& query, + QString& errorMessage); + + static void webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const AFCSettings& settings); + + static void webapiUpdateFeatureSettings( + AFCSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response); + + static const QString m_featureIdURI; + static const QString m_featureId; + +private: + QThread m_thread; + AFCWorker *m_worker; + AFCSettings m_settings; + bool m_ptt; + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + void start(); + void stop(); + void applySettings(const AFCSettings& settings, bool force = false); + void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); + void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AFCSettings& settings, bool force); + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // INCLUDE_FEATURE_AFC_H_ diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp new file mode 100644 index 000000000..9d7ae8353 --- /dev/null +++ b/plugins/feature/afc/afcgui.cpp @@ -0,0 +1,397 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 <QMessageBox> + +#include "feature/featureuiset.h" +#include "gui/basicfeaturesettingsdialog.h" +#include "device/deviceset.h" +#include "maincore.h" + +#include "ui_afcgui.h" +#include "afcreport.h" +#include "afc.h" +#include "afcgui.h" + +AFCGUI* AFCGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature) +{ + AFCGUI* gui = new AFCGUI(pluginAPI, featureUISet, feature); + return gui; +} + +void AFCGUI::destroy() +{ + delete this; +} + +void AFCGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); +} + +QByteArray AFCGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool AFCGUI::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + displaySettings(); + applySettings(true); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +bool AFCGUI::handleMessage(const Message& message) +{ + if (AFC::MsgConfigureAFC::match(message)) + { + qDebug("AFCGUI::handleMessage: AFC::MsgConfigureAFC"); + const AFC::MsgConfigureAFC& cfg = (AFC::MsgConfigureAFC&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + + return true; + } + else if (AFCReport::MsgRadioState::match(message)) + { + qDebug("AFCGUI::handleMessage: AFCReport::MsgRadioState"); + const AFCReport::MsgRadioState& cfg = (AFCReport::MsgRadioState&) message; + AFCReport::RadioState state = cfg.getState(); + ui->statusIndicator->setStyleSheet("QLabel { background-color: " + + m_statusColors[(int) state] + "; border-radius: 12px; }"); + ui->statusIndicator->setToolTip(m_statusTooltips[(int) state]); + + return true; + } + else if (AFC::MsgPTT::match(message)) + { + qDebug("AFCGUI::handleMessage: AFC::MsgPTT"); + const AFC::MsgPTT& cfg = (AFC::MsgPTT&) message; + bool ptt = cfg.getTx(); + blockApplySettings(true); + ui->ptt->setChecked(ptt); + blockApplySettings(false); + + return true; + } + + return false; +} + +void AFCGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop())) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +void AFCGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + (void) widget; + (void) rollDown; +} + +AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) : + FeatureGUI(parent), + ui(new Ui::AFCGUI), + m_pluginAPI(pluginAPI), + m_featureUISet(featureUISet), + m_doApplySettings(true), + m_lastFeatureState(0) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + setChannelWidget(false); + connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + m_simplePTT = reinterpret_cast<AFC*>(feature); + m_simplePTT->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())); + + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(1000); + + m_statusTooltips.push_back("Idle"); // 0 - all off + m_statusTooltips.push_back("Rx on"); // 1 - Rx on + m_statusTooltips.push_back("Tx on"); // 2 - Tx on + + m_statusColors.push_back("gray"); // All off + m_statusColors.push_back("rgb(85, 232, 85)"); // Rx on (green) + m_statusColors.push_back("rgb(232, 85, 85)"); // Tx on (red) + + updateDeviceSetLists(); + displaySettings(); + applySettings(true); +} + +AFCGUI::~AFCGUI() +{ + delete ui; +} + +void AFCGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void AFCGUI::displaySettings() +{ + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_settings.m_title); + blockApplySettings(true); + ui->rxtxDelay->setValue(m_settings.m_rx2TxDelayMs); + ui->txrxDelay->setValue(m_settings.m_tx2RxDelayMs); + blockApplySettings(false); +} + +void AFCGUI::updateDeviceSetLists() +{ + MainCore *mainCore = MainCore::instance(); + std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets(); + std::vector<DeviceSet*>::const_iterator it = deviceSets.begin(); + + ui->rxDevice->blockSignals(true); + ui->txDevice->blockSignals(true); + + ui->rxDevice->clear(); + ui->txDevice->clear(); + unsigned int deviceIndex = 0; + unsigned int rxIndex = 0; + unsigned int txIndex = 0; + + for (; it != deviceSets.end(); ++it, deviceIndex++) + { + DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine; + DSPDeviceSinkEngine *deviceSinkEngine = (*it)->m_deviceSinkEngine; + + if (deviceSourceEngine) + { + ui->rxDevice->addItem(QString("R%1").arg(deviceIndex), deviceIndex); + rxIndex++; + } + else if (deviceSinkEngine) + { + ui->txDevice->addItem(QString("T%1").arg(deviceIndex), deviceIndex); + txIndex++; + } + } + + int rxDeviceIndex; + int txDeviceIndex; + + if (rxIndex > 0) + { + if (m_settings.m_rxDeviceSetIndex < 0) { + ui->rxDevice->setCurrentIndex(0); + } else { + ui->rxDevice->setCurrentIndex(m_settings.m_rxDeviceSetIndex); + } + + rxDeviceIndex = ui->rxDevice->currentData().toInt(); + } + else + { + rxDeviceIndex = -1; + } + + + if (txIndex > 0) + { + if (m_settings.m_txDeviceSetIndex < 0) { + ui->txDevice->setCurrentIndex(0); + } else { + ui->txDevice->setCurrentIndex(m_settings.m_txDeviceSetIndex); + } + + txDeviceIndex = ui->txDevice->currentData().toInt(); + } + else + { + txDeviceIndex = -1; + } + + if ((rxDeviceIndex != m_settings.m_rxDeviceSetIndex) || + (txDeviceIndex != m_settings.m_txDeviceSetIndex)) + { + qDebug("AFCGUI::updateDeviceSetLists: device index changed: %d:%d", rxDeviceIndex, txDeviceIndex); + m_settings.m_rxDeviceSetIndex = rxDeviceIndex; + m_settings.m_txDeviceSetIndex = txDeviceIndex; + applySettings(); + } + + ui->rxDevice->blockSignals(false); + ui->txDevice->blockSignals(false); +} + +void AFCGUI::leaveEvent(QEvent*) +{ +} + +void AFCGUI::enterEvent(QEvent*) +{ +} + +void AFCGUI::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 AFCGUI::on_startStop_toggled(bool checked) +{ + if (m_doApplySettings) + { + AFC::MsgStartStop *message = AFC::MsgStartStop::create(checked); + m_simplePTT->getInputMessageQueue()->push(message); + } +} + +void AFCGUI::on_devicesRefresh_clicked() +{ + updateDeviceSetLists(); + displaySettings(); +} + +void AFCGUI::on_rxDevice_currentIndexChanged(int index) +{ + if (index >= 0) + { + m_settings.m_rxDeviceSetIndex = index; + applySettings(); + } +} + +void AFCGUI::on_txDevice_currentIndexChanged(int index) +{ + if (index >= 0) + { + m_settings.m_txDeviceSetIndex = index; + applySettings(); + } + +} + +void AFCGUI::on_rxtxDelay_valueChanged(int value) +{ + m_settings.m_rx2TxDelayMs = value; + applySettings(); +} + +void AFCGUI::on_txrxDelay_valueChanged(int value) +{ + m_settings.m_tx2RxDelayMs = value; + applySettings(); +} + +void AFCGUI::on_ptt_toggled(bool checked) +{ + applyPTT(checked); +} + +void AFCGUI::updateStatus() +{ + int state = m_simplePTT->getState(); + + if (m_lastFeatureState != state) + { + switch (state) + { + case Feature::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case Feature::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case Feature::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case Feature::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_simplePTT->getErrorMessage()); + break; + default: + break; + } + + m_lastFeatureState = state; + } +} + +void AFCGUI::applySettings(bool force) +{ + if (m_doApplySettings) + { + AFC::MsgConfigureAFC* message = AFC::MsgConfigureAFC::create( m_settings, force); + m_simplePTT->getInputMessageQueue()->push(message); + } +} + +void AFCGUI::applyPTT(bool tx) +{ + if (m_doApplySettings) + { + AFC::MsgPTT* message = AFC::MsgPTT::create(tx); + m_simplePTT->getInputMessageQueue()->push(message); + } +} diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h new file mode 100644 index 000000000..0faa09d7d --- /dev/null +++ b/plugins/feature/afc/afcgui.h @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFCGUI_H_ +#define INCLUDE_FEATURE_AFCGUI_H_ + +#include <QTimer> + +#include "feature/featuregui.h" +#include "util/messagequeue.h" +#include "afcsettings.h" + +class PluginAPI; +class FeatureUISet; +class AFC; + +namespace Ui { + class AFCGUI; +} + +class AFCGUI : public FeatureGUI { + Q_OBJECT +public: + static AFCGUI* 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::AFCGUI* ui; + PluginAPI* m_pluginAPI; + FeatureUISet* m_featureUISet; + AFCSettings m_settings; + bool m_doApplySettings; + + AFC* m_simplePTT; + MessageQueue m_inputMessageQueue; + QTimer m_statusTimer; + int m_lastFeatureState; + std::vector<QString> m_statusColors; + std::vector<QString> m_statusTooltips; + + explicit AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr); + virtual ~AFCGUI(); + + void blockApplySettings(bool block); + void applySettings(bool force = false); + void applyPTT(bool tx); + void displaySettings(); + void updateDeviceSetLists(); + bool handleMessage(const Message& message); + + void leaveEvent(QEvent*); + void enterEvent(QEvent*); + +private slots: + void onMenuDialogCalled(const QPoint &p); + void onWidgetRolled(QWidget* widget, bool rollDown); + void handleInputMessages(); + void on_startStop_toggled(bool checked); + void on_devicesRefresh_clicked(); + void on_rxDevice_currentIndexChanged(int index); + void on_txDevice_currentIndexChanged(int index); + void on_rxtxDelay_valueChanged(int value); + void on_txrxDelay_valueChanged(int value); + void on_ptt_toggled(bool checked); + void updateStatus(); +}; + + +#endif // INCLUDE_FEATURE_AFCGUI_H_ diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui new file mode 100644 index 000000000..d11eb6964 --- /dev/null +++ b/plugins/feature/afc/afcgui.ui @@ -0,0 +1,324 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AFCGUI</class> + <widget class="RollupWidget" name="AFCGUI"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>320</width> + <height>181</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>320</width> + <height>100</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>320</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <family>Liberation Sans</family> + <pointsize>9</pointsize> + </font> + </property> + <property name="windowTitle"> + <string>AFC</string> + </property> + <widget class="QWidget" name="settingsContainer" native="true"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>301</width> + <height>151</height> + </rect> + </property> + <property name="windowTitle"> + <string>Settings</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>3</number> + </property> + <property name="leftMargin"> + <number>2</number> + </property> + <property name="topMargin"> + <number>2</number> + </property> + <property name="rightMargin"> + <number>2</number> + </property> + <property name="bottomMargin"> + <number>2</number> + </property> + <item> + <layout class="QHBoxLayout" name="pttLayout"> + <item> + <widget class="ButtonSwitch" name="startStop"> + <property name="toolTip"> + <string>start/stop acquisition</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/play.png</normaloff> + <normalon>:/stop.png</normalon>:/play.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="ButtonSwitch" name="ptt"> + <property name="minimumSize"> + <size> + <width>200</width> + <height>50</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>20</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="toolTip"> + <string>Push To Talk</string> + </property> + <property name="text"> + <string>PTT</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="statusIndicator"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="toolTip"> + <string>Idle</string> + </property> + <property name="styleSheet"> + <string notr="true">QLabel { background-color: gray; border-radius: 12px; }</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="localDeviceLayout"> + <item> + <widget class="QPushButton" name="devicesRefresh"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Refresh indexes of available device sets</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/recycle.png</normaloff>:/recycle.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="rxDeviceLabel"> + <property name="text"> + <string>Rx dev</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="rxDevice"> + <property name="minimumSize"> + <size> + <width>55</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Receiver deviceset index</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="txDeviceLabel"> + <property name="text"> + <string>Tx dev</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="txDevice"> + <property name="minimumSize"> + <size> + <width>55</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Transmitter deviceset index</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="DelaysLayout"> + <item> + <widget class="QLabel" name="rxtxDelayLabel"> + <property name="text"> + <string>Rx-Tx </string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="rxtxDelay"> + <property name="toolTip"> + <string>Rx to Tx transition delay (ms)</string> + </property> + <property name="minimum"> + <number>100</number> + </property> + <property name="maximum"> + <number>5000</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="rxtxDelayUnits"> + <property name="text"> + <string>ms</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="txrxDelayLabel"> + <property name="toolTip"> + <string/> + </property> + <property name="text"> + <string>Tx-Rx</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="txrxDelay"> + <property name="toolTip"> + <string>Tx to Rx transition delay (ms)</string> + </property> + <property name="minimum"> + <number>100</number> + </property> + <property name="maximum"> + <number>5000</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="txrxDelayUnits"> + <property name="text"> + <string>ms</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + <customwidgets> + <customwidget> + <class>RollupWidget</class> + <extends>QWidget</extends> + <header>gui/rollupwidget.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>ButtonSwitch</class> + <extends>QToolButton</extends> + <header>gui/buttonswitch.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="../../../sdrgui/resources/res.qrc"/> + </resources> + <connections/> +</ui> diff --git a/plugins/feature/afc/afcplugin.cpp b/plugins/feature/afc/afcplugin.cpp new file mode 100644 index 000000000..89bb77f3c --- /dev/null +++ b/plugins/feature/afc/afcplugin.cpp @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "afcgui.h" +#endif +#include "afc.h" +#include "afcplugin.h" +#include "afcwebapiadapter.h" + +const PluginDescriptor AFCPlugin::m_pluginDescriptor = { + AFC::m_featureId, + QString("AFC"), + QString("4.21.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +AFCPlugin::AFCPlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(nullptr) +{ +} + +const PluginDescriptor& AFCPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void AFCPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + // register AFC feature + m_pluginAPI->registerFeature(AFC::m_featureIdURI, AFC::m_featureId, this); +} + +#ifdef SERVER_MODE +FeatureGUI* AFCPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + (void) featureUISet; + (void) feature; + return nullptr; +} +#else +FeatureGUI* AFCPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + return AFCGUI::create(m_pluginAPI, featureUISet, feature); +} +#endif + +Feature* AFCPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const +{ + return new AFC(webAPIAdapterInterface); +} + +FeatureWebAPIAdapter* AFCPlugin::createFeatureWebAPIAdapter() const +{ + return new AFCWebAPIAdapter(); +} diff --git a/plugins/feature/afc/afcplugin.h b/plugins/feature/afc/afcplugin.h new file mode 100644 index 000000000..eea88635a --- /dev/null +++ b/plugins/feature/afc/afcplugin.h @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFCPLUGIN_H +#define INCLUDE_FEATURE_AFCPLUGIN_H + +#include <QObject> +#include "plugin/plugininterface.h" + +class FeatureGUI; +class WebAPIAdapterInterface; + +class AFCPlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.feature.afc") + +public: + explicit AFCPlugin(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_AFCPLUGIN_H diff --git a/plugins/feature/afc/afcreport.cpp b/plugins/feature/afc/afcreport.cpp new file mode 100644 index 000000000..105de5d52 --- /dev/null +++ b/plugins/feature/afc/afcreport.cpp @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "afcreport.h" + +MESSAGE_CLASS_DEFINITION(AFCReport::MsgRadioState, Message) + +AFCReport::AFCReport() +{} + +AFCReport::~AFCReport() +{} diff --git a/plugins/feature/afc/afcreport.h b/plugins/feature/afc/afcreport.h new file mode 100644 index 000000000..97f94f99d --- /dev/null +++ b/plugins/feature/afc/afcreport.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFCREPORT_H_ +#define INCLUDE_FEATURE_AFCREPORT_H_ + +#include "util/message.h" + +class AFCReport +{ +public: + enum RadioState { + RadioIdle, + RadioRx, + RadioTx + }; + class MsgRadioState : public Message { + MESSAGE_CLASS_DECLARATION + + public: + RadioState getState() const { return m_state; } + + static MsgRadioState* create(RadioState state) + { + return new MsgRadioState(state); + } + + private: + RadioState m_state; + + MsgRadioState(RadioState state) : + Message(), + m_state(state) + { } + }; + + AFCReport(); + ~AFCReport(); +}; + +#endif // INCLUDE_FEATURE_AFCREPORT_H_ diff --git a/plugins/feature/afc/afcsettings.cpp b/plugins/feature/afc/afcsettings.cpp new file mode 100644 index 000000000..8ab695009 --- /dev/null +++ b/plugins/feature/afc/afcsettings.cpp @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "afcsettings.h" + +AFCSettings::AFCSettings() +{ + resetToDefaults(); +} + +void AFCSettings::resetToDefaults() +{ + m_title = "AFC"; + m_rgbColor = QColor(255, 255, 0).rgb(); + m_rxDeviceSetIndex = -1; + m_txDeviceSetIndex = -1; + m_rx2TxDelayMs = 100; + m_tx2RxDelayMs = 100; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIFeatureSetIndex = 0; + m_reverseAPIFeatureIndex = 0; +} + +QByteArray AFCSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeString(1, m_title); + s.writeU32(2, m_rgbColor); + s.writeS32(3, m_rxDeviceSetIndex); + s.writeS32(4, m_txDeviceSetIndex); + s.writeU32(5, m_rx2TxDelayMs); + s.writeU32(6, m_tx2RxDelayMs); + s.writeBool(7, m_useReverseAPI); + s.writeString(8, m_reverseAPIAddress); + s.writeU32(9, m_reverseAPIPort); + s.writeU32(10, m_reverseAPIFeatureSetIndex); + s.writeU32(11, m_reverseAPIFeatureIndex); + + return s.final(); +} + +bool AFCSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + qint32 tmp; + uint32_t utmp; + QString strtmp; + + d.readString(1, &m_title, "AFC"); + d.readU32(2, &m_rgbColor, QColor(255, 255, 0).rgb()); + d.readS32(3, &m_rxDeviceSetIndex, -1); + d.readS32(4, &m_txDeviceSetIndex, -1); + d.readU32(5, &m_rx2TxDelayMs, 100); + d.readU32(6, &m_tx2RxDelayMs, 100); + d.readBool(7, &m_useReverseAPI, false); + d.readString(8, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(9, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(10, &utmp, 0); + m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp; + d.readU32(11, &utmp, 0); + m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp; + + return true; + } + else + { + resetToDefaults(); + return false; + } +} diff --git a/plugins/feature/afc/afcsettings.h b/plugins/feature/afc/afcsettings.h new file mode 100644 index 000000000..8dcf0c8b1 --- /dev/null +++ b/plugins/feature/afc/afcsettings.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFCSETTINGS_H_ +#define INCLUDE_FEATURE_AFCSETTINGS_H_ + +#include <QByteArray> +#include <QString> + +class Serializable; + +struct AFCSettings +{ + QString m_title; + quint32 m_rgbColor; + int m_rxDeviceSetIndex; + int m_txDeviceSetIndex; + unsigned int m_rx2TxDelayMs; + unsigned int m_tx2RxDelayMs; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIFeatureSetIndex; + uint16_t m_reverseAPIFeatureIndex; + + AFCSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif // INCLUDE_FEATURE_AFCSETTINGS_H_ diff --git a/plugins/feature/afc/afcwebapiadapter.cpp b/plugins/feature/afc/afcwebapiadapter.cpp new file mode 100644 index 000000000..a34c36ed1 --- /dev/null +++ b/plugins/feature/afc/afcwebapiadapter.cpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "afc.h" +#include "afcwebapiadapter.h" + +AFCWebAPIAdapter::AFCWebAPIAdapter() +{} + +AFCWebAPIAdapter::~AFCWebAPIAdapter() +{} + +int AFCWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAfcSettings(new SWGSDRangel::SWGAFCSettings()); + response.getAfcSettings()->init(); + AFC::webapiFormatFeatureSettings(response, m_settings); + + return 200; +} + +int AFCWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + AFC::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response); + + return 200; +} diff --git a/plugins/feature/afc/afcwebapiadapter.h b/plugins/feature/afc/afcwebapiadapter.h new file mode 100644 index 000000000..f53cc6c42 --- /dev/null +++ b/plugins/feature/afc/afcwebapiadapter.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFC_WEBAPIADAPTER_H +#define INCLUDE_AFC_WEBAPIADAPTER_H + +#include "feature/featurewebapiadapter.h" +#include "afcsettings.h" + +/** + * Standalone API adapter only for the settings + */ +class AFCWebAPIAdapter : public FeatureWebAPIAdapter { +public: + AFCWebAPIAdapter(); + virtual ~AFCWebAPIAdapter(); + + 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: + AFCSettings m_settings; +}; + +#endif // INCLUDE_AFC_WEBAPIADAPTER_H diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp new file mode 100644 index 000000000..1891b4a77 --- /dev/null +++ b/plugins/feature/afc/afcworker.cpp @@ -0,0 +1,210 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "SWGDeviceState.h" +#include "SWGSuccessResponse.h" +#include "SWGErrorResponse.h" + +#include "webapi/webapiadapterinterface.h" + +#include "afcreport.h" +#include "afcworker.h" + +MESSAGE_CLASS_DEFINITION(AFCWorker::MsgConfigureAFCWorker, Message) +MESSAGE_CLASS_DEFINITION(AFCWorker::MsgPTT, Message) + +AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : + m_webAPIAdapterInterface(webAPIAdapterInterface), + m_msgQueueToGUI(nullptr), + m_running(false), + m_tx(false), + m_mutex(QMutex::Recursive) +{ + qDebug("AFCWorker::AFCWorker"); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); +} + +AFCWorker::~AFCWorker() +{ + m_inputMessageQueue.clear(); +} + +void AFCWorker::reset() +{ + QMutexLocker mutexLocker(&m_mutex); + m_inputMessageQueue.clear(); +} + +bool AFCWorker::startWork() +{ + QMutexLocker mutexLocker(&m_mutex); + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_running = true; + return m_running; +} + +void AFCWorker::stopWork() +{ + QMutexLocker mutexLocker(&m_mutex); + disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_running = false; +} + +void AFCWorker::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +bool AFCWorker::handleMessage(const Message& cmd) +{ + if (MsgConfigureAFCWorker::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + MsgConfigureAFCWorker& cfg = (MsgConfigureAFCWorker&) cmd; + qDebug() << "AFCWorker::handleMessage: MsgConfigureAFCWorker"; + + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (MsgPTT::match(cmd)) + { + MsgPTT& cfg = (MsgPTT&) cmd; + qDebug() << "AFCWorker::handleMessage: MsgPTT"; + + sendPTT(cfg.getTx()); + + return true; + } + else + { + return false; + } +} + +void AFCWorker::applySettings(const AFCSettings& settings, bool force) +{ + qDebug() << "AFCWorker::applySettings:" + << " m_title: " << settings.m_title + << " m_rgbColor: " << settings.m_rgbColor + << " m_rxDeviceSetIndex: " << settings.m_rxDeviceSetIndex + << " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex + << " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs + << " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs + << " force: " << force; + m_settings = settings; +} + +void AFCWorker::sendPTT(bool tx) +{ + if (!m_updateTimer.isActive()) + { + bool switchedOff = false; + m_mutex.lock(); + + if (tx) + { + if (m_settings.m_rxDeviceSetIndex >= 0) + { + m_tx = false; + switchedOff = turnDevice(false); + } + + if (m_settings.m_txDeviceSetIndex >= 0) + { + m_tx = true; + m_updateTimer.start(m_settings.m_rx2TxDelayMs); + } + } + else + { + if (m_settings.m_txDeviceSetIndex >= 0) + { + m_tx = true; + switchedOff = turnDevice(false); + } + + if (m_settings.m_rxDeviceSetIndex >= 0) + { + m_tx = false; + m_updateTimer.start(m_settings.m_tx2RxDelayMs); + } + } + + if (switchedOff && (m_msgQueueToGUI)) + { + AFCReport::MsgRadioState *msg = AFCReport::MsgRadioState::create(AFCReport::RadioIdle); + m_msgQueueToGUI->push(msg); + } + } +} + +void AFCWorker::updateHardware() +{ + SWGSDRangel::SWGSuccessResponse response; + SWGSDRangel::SWGErrorResponse error; + m_updateTimer.stop(); + m_mutex.unlock(); + + if (turnDevice(true)) + { + m_webAPIAdapterInterface->devicesetFocusPatch( + m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); + + if (m_msgQueueToGUI) + { + AFCReport::MsgRadioState *msg = AFCReport::MsgRadioState::create( + m_tx ? AFCReport::RadioTx : AFCReport::RadioRx + ); + m_msgQueueToGUI->push(msg); + } + } +} + +bool AFCWorker::turnDevice(bool on) +{ + SWGSDRangel::SWGDeviceState response; + SWGSDRangel::SWGErrorResponse error; + int httpCode; + + if (on) { + httpCode = m_webAPIAdapterInterface->devicesetDeviceRunPost( + m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); + } else { + httpCode = m_webAPIAdapterInterface->devicesetDeviceRunDelete( + m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); + } + + if (httpCode/100 == 2) + { + return true; + } + else + { + qWarning("AFCWorker::turnDevice: error: %s", qPrintable(*error.getMessage())); + return false; + } +} diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h new file mode 100644 index 000000000..86ef75b22 --- /dev/null +++ b/plugins/feature/afc/afcworker.h @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_AFCWORKER_H_ +#define INCLUDE_FEATURE_AFCWORKER_H_ + +#include <QObject> +#include <QTimer> + +#include "util/message.h" +#include "util/messagequeue.h" + +#include "afcsettings.h" + +class WebAPIAdapterInterface; + +class AFCWorker : public QObject +{ + Q_OBJECT +public: + class MsgConfigureAFCWorker : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const AFCSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureAFCWorker* create(const AFCSettings& settings, bool force) + { + return new MsgConfigureAFCWorker(settings, force); + } + + private: + AFCSettings m_settings; + bool m_force; + + MsgConfigureAFCWorker(const AFCSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgPTT : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getTx() const { return m_tx; } + + static MsgPTT* create(bool tx) { + return new MsgPTT(tx); + } + + private: + bool m_tx; + + MsgPTT(bool tx) : + Message(), + m_tx(tx) + { } + }; + + AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface); + ~AFCWorker(); + void reset(); + bool startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; } + +private: + WebAPIAdapterInterface *m_webAPIAdapterInterface; + MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication + MessageQueue *m_msgQueueToGUI; //!< Queue to report state to GUI + AFCSettings m_settings; + bool m_running; + bool m_tx; + QTimer m_updateTimer; + QMutex m_mutex; + + bool handleMessage(const Message& cmd); + void applySettings(const AFCSettings& settings, bool force = false); + void sendPTT(bool tx); + bool turnDevice(bool on); + +private slots: + void handleInputMessages(); + void updateHardware(); +}; + +#endif // INCLUDE_FEATURE_SIMPLEPTTWORKER_H_ diff --git a/plugins/feature/afc/readme.md b/plugins/feature/afc/readme.md new file mode 100644 index 000000000..6d60f5b16 --- /dev/null +++ b/plugins/feature/afc/readme.md @@ -0,0 +1,45 @@ +<h1>AFC plugin</h1> + +<h2>Introduction</h2> + +This plugin controls switchover between a Rx (Device source) and Tx (Device sink). It has no other controls than an adjustable delay from Rx to Tx and back to Rx. Because of its simplicity it can also serve as a model to build other feature plugins. + +<h2>Interface</h2> + + + +<h3>1: Start/Stop plugin</h3> + +This button starts or stops the plugin + +<h3>2: PTT button</h3> + +Click to switch from Rx to Tx and again to switch back to Rx. When in Tx mode the button is lit. + +<h3>3: Status indicator</h3> + +This LED type display shows the current PTT status: + + - **Green**: Rx runs + - **Red**: Tx runs + - **Grey**: None active (transient) + +<h3>4: Refresh list of devices</h3> + +Use this button to refresh the list of devices (5) and (6) + +<h3>5: Select Rx device set</h3> + +Use this combo to select which Rx device is controlled + +<h3>6: Select Tx device set</h3> + +Use this combo to select which Tx device is controlled + +<h3>7: Transistion delay from Rx to Tx</h3> + +Value in milliseconds between Rx stop and Tx start + +<h3>8: Transistion delay from Tx to Rx</h3> + +Value in milliseconds between Tx stop and Rx start From ffdc6f69f0de1776d677416f40cade507c8a02b4 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 17 Oct 2020 23:41:54 +0200 Subject: [PATCH 03/27] AFC: settings fix REST API sources --- swagger/sdrangel/api/swagger/include/AFC.yaml | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/swagger/sdrangel/api/swagger/include/AFC.yaml b/swagger/sdrangel/api/swagger/include/AFC.yaml index 4397ab890..4781ce38b 100644 --- a/swagger/sdrangel/api/swagger/include/AFC.yaml +++ b/swagger/sdrangel/api/swagger/include/AFC.yaml @@ -5,18 +5,32 @@ AFCSettings: type: string rgbColor: type: integer - rxDeviceSetIndex: - description: index of the Rx device set to connect the Rx side to + trackerDeviceSetIndex: + description: index of the device set of frequency tracker being used type: integer - txDeviceSetIndex: - description: index of the Tx device set to connect the Tx side to + trackedDeviceSetIndex: + description: index of the device set being tracked (channels and possibly device) type: integer - rx2TxDelayMs: - description: Delay in milliseconds from Rx off to Tx on + hasTargetFrequency: type: integer - tx2RxDelayMs: - description: Delay in milliseconds from Tx off to Rx on + description: > + Adjust device frequency to match tracker frequency + * 0 - disabled + * 1 - enabled + transverterTarget: type: integer + description: > + Use transverter or device frequency for tracker frequency adjustment + * 0 - device + * 1 - transverter + targetFrequency: + description: Target frequency for the tracker + type: integer + format: int64 + freqTolerance: + descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted + type: integer + format: int64 useReverseAPI: description: Synchronize with reverse API (1 for yes, 0 for no) type: integer From 4ac114a924a2f98db040ee36ee0c20cb7dbea796 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Tue, 27 Oct 2020 06:01:57 +0100 Subject: [PATCH 04/27] AFC: settings fix REST API sources: generated code --- sdrbase/resources/webapi/doc/html2/index.html | 81 +++- .../webapi/doc/swagger/include/AFC.yaml | 64 +++ .../doc/swagger/include/FeatureActions.yaml | 2 + .../doc/swagger/include/FeatureReport.yaml | 2 + .../doc/swagger/include/FeatureSettings.yaml | 2 + swagger/sdrangel/code/html2/index.html | 81 +++- .../code/qt5/client/SWGAFCActions.cpp | 108 +++++ .../sdrangel/code/qt5/client/SWGAFCActions.h | 58 +++ .../sdrangel/code/qt5/client/SWGAFCReport.cpp | 108 +++++ .../sdrangel/code/qt5/client/SWGAFCReport.h | 58 +++ .../code/qt5/client/SWGAFCSettings.cpp | 388 ++++++++++++++++++ .../sdrangel/code/qt5/client/SWGAFCSettings.h | 131 ++++++ .../code/qt5/client/SWGFeatureActions.cpp | 25 ++ .../code/qt5/client/SWGFeatureActions.h | 7 + .../code/qt5/client/SWGFeatureReport.cpp | 25 ++ .../code/qt5/client/SWGFeatureReport.h | 7 + .../code/qt5/client/SWGFeatureSettings.cpp | 25 ++ .../code/qt5/client/SWGFeatureSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 12 + 19 files changed, 1189 insertions(+), 2 deletions(-) create mode 100644 sdrbase/resources/webapi/doc/swagger/include/AFC.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCActions.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCReport.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGAFCSettings.h diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 2dd81cdeb..977025a24 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -696,6 +696,76 @@ margin-bottom: 20px; <script> // Script section to load models into a JS Var var defs = {} + defs.AFCActions = { + "properties" : { + "ptt" : { + "type" : "integer", + "description" : "AFC action\n * 0 - release\n * 1 - engage\n" + } + }, + "description" : "AFC actions" +}; + defs.AFCReport = { + "properties" : { + "ptt" : { + "type" : "integer", + "description" : "AFC status\n * 0 - released\n * 1 - engaged\n" + } + }, + "description" : "AFC report" +}; + defs.AFCSettings = { + "properties" : { + "title" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "trackerDeviceSetIndex" : { + "type" : "integer", + "description" : "index of the device set of frequency tracker being used" + }, + "trackedDeviceSetIndex" : { + "type" : "integer", + "description" : "index of the device set being tracked (channels and possibly device)" + }, + "hasTargetFrequency" : { + "type" : "integer", + "description" : "Adjust device frequency to match tracker frequency\n * 0 - disabled\n * 1 - enabled\n" + }, + "transverterTarget" : { + "type" : "integer", + "description" : "Use transverter or device frequency for tracker frequency adjustment\n * 0 - device\n * 1 - transverter\n" + }, + "targetFrequency" : { + "type" : "integer", + "format" : "int64", + "description" : "Target frequency for the tracker" + }, + "freqTolerance" : { + "type" : "integer", + "format" : "int64" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "AFC settings" +}; defs.AMBEDevice = { "properties" : { "deviceRef" : { @@ -3202,6 +3272,9 @@ margin-bottom: 20px; "type" : "integer", "description" : "Optional for reverse API. This is the feature index from where the message comes from." }, + "AFCActions" : { + "$ref" : "#/definitions/AFCActions" + }, "SimplePTTActions" : { "$ref" : "#/definitions/SimplePTTActions" } @@ -3228,6 +3301,9 @@ margin-bottom: 20px; "type" : "string", "description" : "Feature type code" }, + "AFCReport" : { + "$ref" : "#/definitions/AFCReport" + }, "SimplePTTReport" : { "$ref" : "#/definitions/SimplePTTReport" } @@ -3300,6 +3376,9 @@ margin-bottom: 20px; "type" : "integer", "description" : "Optional for reverse API. This is the feature index from where the message comes from." }, + "AFCSettings" : { + "$ref" : "#/definitions/AFCSettings" + }, "SimplePTTSettings" : { "$ref" : "#/definitions/SimplePTTSettings" }, @@ -39969,7 +40048,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-11T08:49:12.690+02:00 + Generated 2020-10-27T06:01:09.347+01:00 </div> </div> </div> diff --git a/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml new file mode 100644 index 000000000..4781ce38b --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml @@ -0,0 +1,64 @@ +AFCSettings: + description: "AFC settings" + properties: + title: + type: string + rgbColor: + type: integer + trackerDeviceSetIndex: + description: index of the device set of frequency tracker being used + type: integer + trackedDeviceSetIndex: + description: index of the device set being tracked (channels and possibly device) + type: integer + hasTargetFrequency: + type: integer + description: > + Adjust device frequency to match tracker frequency + * 0 - disabled + * 1 - enabled + transverterTarget: + type: integer + description: > + Use transverter or device frequency for tracker frequency adjustment + * 0 - device + * 1 - transverter + targetFrequency: + description: Target frequency for the tracker + type: integer + format: int64 + freqTolerance: + descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted + type: integer + format: int64 + 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 + +AFCReport: + description: "AFC report" + properties: + ptt: + type: integer + description: > + AFC status + * 0 - released + * 1 - engaged + +AFCActions: + description: "AFC actions" + properties: + ptt: + type: integer + description: > + AFC action + * 0 - release + * 1 - engage diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml index dbdea0da6..1dd79cbbf 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml @@ -13,5 +13,7 @@ FeatureActions: originatorFeatureIndex: description: Optional for reverse API. This is the feature index from where the message comes from. type: integer + AFCActions: + $ref: "/doc/swagger/include/AFC.yaml#/AFCActions" SimplePTTActions: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTActions" diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml index 52ad07b14..9fd5a1f0d 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml @@ -7,5 +7,7 @@ FeatureReport: featureType: description: Feature type code type: string + AFCReport: + $ref: "/doc/swagger/include/AFC.yaml#/AFCReport" SimplePTTReport: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTReport" diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml index 4f5b69c83..b9c2e7a2a 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml @@ -13,6 +13,8 @@ FeatureSettings: originatorFeatureIndex: description: Optional for reverse API. This is the feature index from where the message comes from. type: integer + AFCSettings: + $ref: "/doc/swagger/include/AFC.yaml#/AFCSettings" SimplePTTSettings: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTSettings" RigCtlServerSettings: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 2dd81cdeb..977025a24 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -696,6 +696,76 @@ margin-bottom: 20px; <script> // Script section to load models into a JS Var var defs = {} + defs.AFCActions = { + "properties" : { + "ptt" : { + "type" : "integer", + "description" : "AFC action\n * 0 - release\n * 1 - engage\n" + } + }, + "description" : "AFC actions" +}; + defs.AFCReport = { + "properties" : { + "ptt" : { + "type" : "integer", + "description" : "AFC status\n * 0 - released\n * 1 - engaged\n" + } + }, + "description" : "AFC report" +}; + defs.AFCSettings = { + "properties" : { + "title" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "trackerDeviceSetIndex" : { + "type" : "integer", + "description" : "index of the device set of frequency tracker being used" + }, + "trackedDeviceSetIndex" : { + "type" : "integer", + "description" : "index of the device set being tracked (channels and possibly device)" + }, + "hasTargetFrequency" : { + "type" : "integer", + "description" : "Adjust device frequency to match tracker frequency\n * 0 - disabled\n * 1 - enabled\n" + }, + "transverterTarget" : { + "type" : "integer", + "description" : "Use transverter or device frequency for tracker frequency adjustment\n * 0 - device\n * 1 - transverter\n" + }, + "targetFrequency" : { + "type" : "integer", + "format" : "int64", + "description" : "Target frequency for the tracker" + }, + "freqTolerance" : { + "type" : "integer", + "format" : "int64" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "AFC settings" +}; defs.AMBEDevice = { "properties" : { "deviceRef" : { @@ -3202,6 +3272,9 @@ margin-bottom: 20px; "type" : "integer", "description" : "Optional for reverse API. This is the feature index from where the message comes from." }, + "AFCActions" : { + "$ref" : "#/definitions/AFCActions" + }, "SimplePTTActions" : { "$ref" : "#/definitions/SimplePTTActions" } @@ -3228,6 +3301,9 @@ margin-bottom: 20px; "type" : "string", "description" : "Feature type code" }, + "AFCReport" : { + "$ref" : "#/definitions/AFCReport" + }, "SimplePTTReport" : { "$ref" : "#/definitions/SimplePTTReport" } @@ -3300,6 +3376,9 @@ margin-bottom: 20px; "type" : "integer", "description" : "Optional for reverse API. This is the feature index from where the message comes from." }, + "AFCSettings" : { + "$ref" : "#/definitions/AFCSettings" + }, "SimplePTTSettings" : { "$ref" : "#/definitions/SimplePTTSettings" }, @@ -39969,7 +40048,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-11T08:49:12.690+02:00 + Generated 2020-10-27T06:01:09.347+01:00 </div> </div> </div> diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp new file mode 100644 index 000000000..357ca5338 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp @@ -0,0 +1,108 @@ +/** + * 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, USRP 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: 4.15.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 "SWGAFCActions.h" + +#include "SWGHelpers.h" + +#include <QJsonDocument> +#include <QJsonArray> +#include <QObject> +#include <QDebug> + +namespace SWGSDRangel { + +SWGAFCActions::SWGAFCActions(QString* json) { + init(); + this->fromJson(*json); +} + +SWGAFCActions::SWGAFCActions() { + ptt = 0; + m_ptt_isSet = false; +} + +SWGAFCActions::~SWGAFCActions() { + this->cleanup(); +} + +void +SWGAFCActions::init() { + ptt = 0; + m_ptt_isSet = false; +} + +void +SWGAFCActions::cleanup() { + +} + +SWGAFCActions* +SWGAFCActions::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGAFCActions::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&ptt, pJson["ptt"], "qint32", ""); + +} + +QString +SWGAFCActions::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGAFCActions::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_ptt_isSet){ + obj->insert("ptt", QJsonValue(ptt)); + } + + return obj; +} + +qint32 +SWGAFCActions::getPtt() { + return ptt; +} +void +SWGAFCActions::setPtt(qint32 ptt) { + this->ptt = ptt; + this->m_ptt_isSet = true; +} + + +bool +SWGAFCActions::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_ptt_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCActions.h b/swagger/sdrangel/code/qt5/client/SWGAFCActions.h new file mode 100644 index 000000000..e25947dcc --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCActions.h @@ -0,0 +1,58 @@ +/** + * 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, USRP 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: 4.15.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. + */ + +/* + * SWGAFCActions.h + * + * AFC actions + */ + +#ifndef SWGAFCActions_H_ +#define SWGAFCActions_H_ + +#include <QJsonObject> + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGAFCActions: public SWGObject { +public: + SWGAFCActions(); + SWGAFCActions(QString* json); + virtual ~SWGAFCActions(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGAFCActions* fromJson(QString &jsonString) override; + + qint32 getPtt(); + void setPtt(qint32 ptt); + + + virtual bool isSet() override; + +private: + qint32 ptt; + bool m_ptt_isSet; + +}; + +} + +#endif /* SWGAFCActions_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp new file mode 100644 index 000000000..89baca1eb --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp @@ -0,0 +1,108 @@ +/** + * 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, USRP 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: 4.15.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 "SWGAFCReport.h" + +#include "SWGHelpers.h" + +#include <QJsonDocument> +#include <QJsonArray> +#include <QObject> +#include <QDebug> + +namespace SWGSDRangel { + +SWGAFCReport::SWGAFCReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGAFCReport::SWGAFCReport() { + ptt = 0; + m_ptt_isSet = false; +} + +SWGAFCReport::~SWGAFCReport() { + this->cleanup(); +} + +void +SWGAFCReport::init() { + ptt = 0; + m_ptt_isSet = false; +} + +void +SWGAFCReport::cleanup() { + +} + +SWGAFCReport* +SWGAFCReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGAFCReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&ptt, pJson["ptt"], "qint32", ""); + +} + +QString +SWGAFCReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGAFCReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_ptt_isSet){ + obj->insert("ptt", QJsonValue(ptt)); + } + + return obj; +} + +qint32 +SWGAFCReport::getPtt() { + return ptt; +} +void +SWGAFCReport::setPtt(qint32 ptt) { + this->ptt = ptt; + this->m_ptt_isSet = true; +} + + +bool +SWGAFCReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_ptt_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCReport.h b/swagger/sdrangel/code/qt5/client/SWGAFCReport.h new file mode 100644 index 000000000..8125dea81 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCReport.h @@ -0,0 +1,58 @@ +/** + * 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, USRP 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: 4.15.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. + */ + +/* + * SWGAFCReport.h + * + * AFC report + */ + +#ifndef SWGAFCReport_H_ +#define SWGAFCReport_H_ + +#include <QJsonObject> + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGAFCReport: public SWGObject { +public: + SWGAFCReport(); + SWGAFCReport(QString* json); + virtual ~SWGAFCReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGAFCReport* fromJson(QString &jsonString) override; + + qint32 getPtt(); + void setPtt(qint32 ptt); + + + virtual bool isSet() override; + +private: + qint32 ptt; + bool m_ptt_isSet; + +}; + +} + +#endif /* SWGAFCReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp new file mode 100644 index 000000000..012e3096c --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.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, USRP 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: 4.15.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 "SWGAFCSettings.h" + +#include "SWGHelpers.h" + +#include <QJsonDocument> +#include <QJsonArray> +#include <QObject> +#include <QDebug> + +namespace SWGSDRangel { + +SWGAFCSettings::SWGAFCSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGAFCSettings::SWGAFCSettings() { + title = nullptr; + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + tracker_device_set_index = 0; + m_tracker_device_set_index_isSet = false; + tracked_device_set_index = 0; + m_tracked_device_set_index_isSet = false; + has_target_frequency = 0; + m_has_target_frequency_isSet = false; + transverter_target = 0; + m_transverter_target_isSet = false; + target_frequency = 0L; + m_target_frequency_isSet = false; + freq_tolerance = 0L; + m_freq_tolerance_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; +} + +SWGAFCSettings::~SWGAFCSettings() { + this->cleanup(); +} + +void +SWGAFCSettings::init() { + title = new QString(""); + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + tracker_device_set_index = 0; + m_tracker_device_set_index_isSet = false; + tracked_device_set_index = 0; + m_tracked_device_set_index_isSet = false; + has_target_frequency = 0; + m_has_target_frequency_isSet = false; + transverter_target = 0; + m_transverter_target_isSet = false; + target_frequency = 0L; + m_target_frequency_isSet = false; + freq_tolerance = 0L; + m_freq_tolerance_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 +SWGAFCSettings::cleanup() { + if(title != nullptr) { + delete title; + } + + + + + + + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + +} + +SWGAFCSettings* +SWGAFCSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGAFCSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&tracker_device_set_index, pJson["trackerDeviceSetIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&tracked_device_set_index, pJson["trackedDeviceSetIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&has_target_frequency, pJson["hasTargetFrequency"], "qint32", ""); + + ::SWGSDRangel::setValue(&transverter_target, pJson["transverterTarget"], "qint32", ""); + + ::SWGSDRangel::setValue(&target_frequency, pJson["targetFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&freq_tolerance, pJson["freqTolerance"], "qint64", ""); + + ::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 +SWGAFCSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGAFCSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + 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_tracker_device_set_index_isSet){ + obj->insert("trackerDeviceSetIndex", QJsonValue(tracker_device_set_index)); + } + if(m_tracked_device_set_index_isSet){ + obj->insert("trackedDeviceSetIndex", QJsonValue(tracked_device_set_index)); + } + if(m_has_target_frequency_isSet){ + obj->insert("hasTargetFrequency", QJsonValue(has_target_frequency)); + } + if(m_transverter_target_isSet){ + obj->insert("transverterTarget", QJsonValue(transverter_target)); + } + if(m_target_frequency_isSet){ + obj->insert("targetFrequency", QJsonValue(target_frequency)); + } + if(m_freq_tolerance_isSet){ + obj->insert("freqTolerance", QJsonValue(freq_tolerance)); + } + 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; +} + +QString* +SWGAFCSettings::getTitle() { + return title; +} +void +SWGAFCSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGAFCSettings::getRgbColor() { + return rgb_color; +} +void +SWGAFCSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +qint32 +SWGAFCSettings::getTrackerDeviceSetIndex() { + return tracker_device_set_index; +} +void +SWGAFCSettings::setTrackerDeviceSetIndex(qint32 tracker_device_set_index) { + this->tracker_device_set_index = tracker_device_set_index; + this->m_tracker_device_set_index_isSet = true; +} + +qint32 +SWGAFCSettings::getTrackedDeviceSetIndex() { + return tracked_device_set_index; +} +void +SWGAFCSettings::setTrackedDeviceSetIndex(qint32 tracked_device_set_index) { + this->tracked_device_set_index = tracked_device_set_index; + this->m_tracked_device_set_index_isSet = true; +} + +qint32 +SWGAFCSettings::getHasTargetFrequency() { + return has_target_frequency; +} +void +SWGAFCSettings::setHasTargetFrequency(qint32 has_target_frequency) { + this->has_target_frequency = has_target_frequency; + this->m_has_target_frequency_isSet = true; +} + +qint32 +SWGAFCSettings::getTransverterTarget() { + return transverter_target; +} +void +SWGAFCSettings::setTransverterTarget(qint32 transverter_target) { + this->transverter_target = transverter_target; + this->m_transverter_target_isSet = true; +} + +qint64 +SWGAFCSettings::getTargetFrequency() { + return target_frequency; +} +void +SWGAFCSettings::setTargetFrequency(qint64 target_frequency) { + this->target_frequency = target_frequency; + this->m_target_frequency_isSet = true; +} + +qint64 +SWGAFCSettings::getFreqTolerance() { + return freq_tolerance; +} +void +SWGAFCSettings::setFreqTolerance(qint64 freq_tolerance) { + this->freq_tolerance = freq_tolerance; + this->m_freq_tolerance_isSet = true; +} + +qint32 +SWGAFCSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGAFCSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGAFCSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGAFCSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGAFCSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGAFCSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGAFCSettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGAFCSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + +qint32 +SWGAFCSettings::getReverseApiChannelIndex() { + return reverse_api_channel_index; +} +void +SWGAFCSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { + this->reverse_api_channel_index = reverse_api_channel_index; + this->m_reverse_api_channel_index_isSet = true; +} + + +bool +SWGAFCSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(m_tracker_device_set_index_isSet){ + isObjectUpdated = true; break; + } + if(m_tracked_device_set_index_isSet){ + isObjectUpdated = true; break; + } + if(m_has_target_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_transverter_target_isSet){ + isObjectUpdated = true; break; + } + if(m_target_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_freq_tolerance_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/SWGAFCSettings.h b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h new file mode 100644 index 000000000..fe1cf6551 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.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, USRP 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: 4.15.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. + */ + +/* + * SWGAFCSettings.h + * + * AFC settings + */ + +#ifndef SWGAFCSettings_H_ +#define SWGAFCSettings_H_ + +#include <QJsonObject> + + +#include <QString> + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGAFCSettings: public SWGObject { +public: + SWGAFCSettings(); + SWGAFCSettings(QString* json); + virtual ~SWGAFCSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGAFCSettings* fromJson(QString &jsonString) override; + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + qint32 getTrackerDeviceSetIndex(); + void setTrackerDeviceSetIndex(qint32 tracker_device_set_index); + + qint32 getTrackedDeviceSetIndex(); + void setTrackedDeviceSetIndex(qint32 tracked_device_set_index); + + qint32 getHasTargetFrequency(); + void setHasTargetFrequency(qint32 has_target_frequency); + + qint32 getTransverterTarget(); + void setTransverterTarget(qint32 transverter_target); + + qint64 getTargetFrequency(); + void setTargetFrequency(qint64 target_frequency); + + qint64 getFreqTolerance(); + void setFreqTolerance(qint64 freq_tolerance); + + 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: + QString* title; + bool m_title_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + qint32 tracker_device_set_index; + bool m_tracker_device_set_index_isSet; + + qint32 tracked_device_set_index; + bool m_tracked_device_set_index_isSet; + + qint32 has_target_frequency; + bool m_has_target_frequency_isSet; + + qint32 transverter_target; + bool m_transverter_target_isSet; + + qint64 target_frequency; + bool m_target_frequency_isSet; + + qint64 freq_tolerance; + bool m_freq_tolerance_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 /* SWGAFCSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp index 8b7fec5ea..8d28c594b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp @@ -34,6 +34,8 @@ SWGFeatureActions::SWGFeatureActions() { m_originator_feature_set_index_isSet = false; originator_feature_index = 0; m_originator_feature_index_isSet = false; + afc_actions = nullptr; + m_afc_actions_isSet = false; simple_ptt_actions = nullptr; m_simple_ptt_actions_isSet = false; } @@ -50,6 +52,8 @@ SWGFeatureActions::init() { m_originator_feature_set_index_isSet = false; originator_feature_index = 0; m_originator_feature_index_isSet = false; + afc_actions = new SWGAFCActions(); + m_afc_actions_isSet = false; simple_ptt_actions = new SWGSimplePTTActions(); m_simple_ptt_actions_isSet = false; } @@ -61,6 +65,9 @@ SWGFeatureActions::cleanup() { } + if(afc_actions != nullptr) { + delete afc_actions; + } if(simple_ptt_actions != nullptr) { delete simple_ptt_actions; } @@ -83,6 +90,8 @@ SWGFeatureActions::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&originator_feature_index, pJson["originatorFeatureIndex"], "qint32", ""); + ::SWGSDRangel::setValue(&afc_actions, pJson["AFCActions"], "SWGAFCActions", "SWGAFCActions"); + ::SWGSDRangel::setValue(&simple_ptt_actions, pJson["SimplePTTActions"], "SWGSimplePTTActions", "SWGSimplePTTActions"); } @@ -110,6 +119,9 @@ SWGFeatureActions::asJsonObject() { if(m_originator_feature_index_isSet){ obj->insert("originatorFeatureIndex", QJsonValue(originator_feature_index)); } + if((afc_actions != nullptr) && (afc_actions->isSet())){ + toJsonValue(QString("AFCActions"), afc_actions, obj, QString("SWGAFCActions")); + } if((simple_ptt_actions != nullptr) && (simple_ptt_actions->isSet())){ toJsonValue(QString("SimplePTTActions"), simple_ptt_actions, obj, QString("SWGSimplePTTActions")); } @@ -147,6 +159,16 @@ SWGFeatureActions::setOriginatorFeatureIndex(qint32 originator_feature_index) { this->m_originator_feature_index_isSet = true; } +SWGAFCActions* +SWGFeatureActions::getAfcActions() { + return afc_actions; +} +void +SWGFeatureActions::setAfcActions(SWGAFCActions* afc_actions) { + this->afc_actions = afc_actions; + this->m_afc_actions_isSet = true; +} + SWGSimplePTTActions* SWGFeatureActions::getSimplePttActions() { return simple_ptt_actions; @@ -171,6 +193,9 @@ SWGFeatureActions::isSet(){ if(m_originator_feature_index_isSet){ isObjectUpdated = true; break; } + if(afc_actions && afc_actions->isSet()){ + isObjectUpdated = true; break; + } if(simple_ptt_actions && simple_ptt_actions->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h index 93715663a..ee21bd369 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h @@ -22,6 +22,7 @@ #include <QJsonObject> +#include "SWGAFCActions.h" #include "SWGSimplePTTActions.h" #include <QString> @@ -52,6 +53,9 @@ public: qint32 getOriginatorFeatureIndex(); void setOriginatorFeatureIndex(qint32 originator_feature_index); + SWGAFCActions* getAfcActions(); + void setAfcActions(SWGAFCActions* afc_actions); + SWGSimplePTTActions* getSimplePttActions(); void setSimplePttActions(SWGSimplePTTActions* simple_ptt_actions); @@ -68,6 +72,9 @@ private: qint32 originator_feature_index; bool m_originator_feature_index_isSet; + SWGAFCActions* afc_actions; + bool m_afc_actions_isSet; + SWGSimplePTTActions* simple_ptt_actions; bool m_simple_ptt_actions_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp index 66b010f40..de5220891 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp @@ -30,6 +30,8 @@ SWGFeatureReport::SWGFeatureReport(QString* json) { SWGFeatureReport::SWGFeatureReport() { feature_type = nullptr; m_feature_type_isSet = false; + afc_report = nullptr; + m_afc_report_isSet = false; simple_ptt_report = nullptr; m_simple_ptt_report_isSet = false; } @@ -42,6 +44,8 @@ void SWGFeatureReport::init() { feature_type = new QString(""); m_feature_type_isSet = false; + afc_report = new SWGAFCReport(); + m_afc_report_isSet = false; simple_ptt_report = new SWGSimplePTTReport(); m_simple_ptt_report_isSet = false; } @@ -51,6 +55,9 @@ SWGFeatureReport::cleanup() { if(feature_type != nullptr) { delete feature_type; } + if(afc_report != nullptr) { + delete afc_report; + } if(simple_ptt_report != nullptr) { delete simple_ptt_report; } @@ -69,6 +76,8 @@ void SWGFeatureReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&feature_type, pJson["featureType"], "QString", "QString"); + ::SWGSDRangel::setValue(&afc_report, pJson["AFCReport"], "SWGAFCReport", "SWGAFCReport"); + ::SWGSDRangel::setValue(&simple_ptt_report, pJson["SimplePTTReport"], "SWGSimplePTTReport", "SWGSimplePTTReport"); } @@ -90,6 +99,9 @@ SWGFeatureReport::asJsonObject() { if(feature_type != nullptr && *feature_type != QString("")){ toJsonValue(QString("featureType"), feature_type, obj, QString("QString")); } + if((afc_report != nullptr) && (afc_report->isSet())){ + toJsonValue(QString("AFCReport"), afc_report, obj, QString("SWGAFCReport")); + } if((simple_ptt_report != nullptr) && (simple_ptt_report->isSet())){ toJsonValue(QString("SimplePTTReport"), simple_ptt_report, obj, QString("SWGSimplePTTReport")); } @@ -107,6 +119,16 @@ SWGFeatureReport::setFeatureType(QString* feature_type) { this->m_feature_type_isSet = true; } +SWGAFCReport* +SWGFeatureReport::getAfcReport() { + return afc_report; +} +void +SWGFeatureReport::setAfcReport(SWGAFCReport* afc_report) { + this->afc_report = afc_report; + this->m_afc_report_isSet = true; +} + SWGSimplePTTReport* SWGFeatureReport::getSimplePttReport() { return simple_ptt_report; @@ -125,6 +147,9 @@ SWGFeatureReport::isSet(){ if(feature_type && *feature_type != QString("")){ isObjectUpdated = true; break; } + if(afc_report && afc_report->isSet()){ + isObjectUpdated = true; break; + } if(simple_ptt_report && simple_ptt_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h index 14473da60..9fc74eb2b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h @@ -22,6 +22,7 @@ #include <QJsonObject> +#include "SWGAFCReport.h" #include "SWGSimplePTTReport.h" #include <QString> @@ -46,6 +47,9 @@ public: QString* getFeatureType(); void setFeatureType(QString* feature_type); + SWGAFCReport* getAfcReport(); + void setAfcReport(SWGAFCReport* afc_report); + SWGSimplePTTReport* getSimplePttReport(); void setSimplePttReport(SWGSimplePTTReport* simple_ptt_report); @@ -56,6 +60,9 @@ private: QString* feature_type; bool m_feature_type_isSet; + SWGAFCReport* afc_report; + bool m_afc_report_isSet; + SWGSimplePTTReport* simple_ptt_report; bool m_simple_ptt_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp index dbe340b7c..889f5a79c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp @@ -34,6 +34,8 @@ SWGFeatureSettings::SWGFeatureSettings() { m_originator_feature_set_index_isSet = false; originator_feature_index = 0; m_originator_feature_index_isSet = false; + afc_settings = nullptr; + m_afc_settings_isSet = false; simple_ptt_settings = nullptr; m_simple_ptt_settings_isSet = false; rig_ctl_server_settings = nullptr; @@ -52,6 +54,8 @@ SWGFeatureSettings::init() { m_originator_feature_set_index_isSet = false; originator_feature_index = 0; m_originator_feature_index_isSet = false; + afc_settings = new SWGAFCSettings(); + m_afc_settings_isSet = false; simple_ptt_settings = new SWGSimplePTTSettings(); m_simple_ptt_settings_isSet = false; rig_ctl_server_settings = new SWGRigCtlServerSettings(); @@ -65,6 +69,9 @@ SWGFeatureSettings::cleanup() { } + if(afc_settings != nullptr) { + delete afc_settings; + } if(simple_ptt_settings != nullptr) { delete simple_ptt_settings; } @@ -90,6 +97,8 @@ SWGFeatureSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&originator_feature_index, pJson["originatorFeatureIndex"], "qint32", ""); + ::SWGSDRangel::setValue(&afc_settings, pJson["AFCSettings"], "SWGAFCSettings", "SWGAFCSettings"); + ::SWGSDRangel::setValue(&simple_ptt_settings, pJson["SimplePTTSettings"], "SWGSimplePTTSettings", "SWGSimplePTTSettings"); ::SWGSDRangel::setValue(&rig_ctl_server_settings, pJson["RigCtlServerSettings"], "SWGRigCtlServerSettings", "SWGRigCtlServerSettings"); @@ -119,6 +128,9 @@ SWGFeatureSettings::asJsonObject() { if(m_originator_feature_index_isSet){ obj->insert("originatorFeatureIndex", QJsonValue(originator_feature_index)); } + if((afc_settings != nullptr) && (afc_settings->isSet())){ + toJsonValue(QString("AFCSettings"), afc_settings, obj, QString("SWGAFCSettings")); + } if((simple_ptt_settings != nullptr) && (simple_ptt_settings->isSet())){ toJsonValue(QString("SimplePTTSettings"), simple_ptt_settings, obj, QString("SWGSimplePTTSettings")); } @@ -159,6 +171,16 @@ SWGFeatureSettings::setOriginatorFeatureIndex(qint32 originator_feature_index) { this->m_originator_feature_index_isSet = true; } +SWGAFCSettings* +SWGFeatureSettings::getAfcSettings() { + return afc_settings; +} +void +SWGFeatureSettings::setAfcSettings(SWGAFCSettings* afc_settings) { + this->afc_settings = afc_settings; + this->m_afc_settings_isSet = true; +} + SWGSimplePTTSettings* SWGFeatureSettings::getSimplePttSettings() { return simple_ptt_settings; @@ -193,6 +215,9 @@ SWGFeatureSettings::isSet(){ if(m_originator_feature_index_isSet){ isObjectUpdated = true; break; } + if(afc_settings && afc_settings->isSet()){ + isObjectUpdated = true; break; + } if(simple_ptt_settings && simple_ptt_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h index 21480f57a..0f0dfc40a 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h @@ -22,6 +22,7 @@ #include <QJsonObject> +#include "SWGAFCSettings.h" #include "SWGRigCtlServerSettings.h" #include "SWGSimplePTTSettings.h" #include <QString> @@ -53,6 +54,9 @@ public: qint32 getOriginatorFeatureIndex(); void setOriginatorFeatureIndex(qint32 originator_feature_index); + SWGAFCSettings* getAfcSettings(); + void setAfcSettings(SWGAFCSettings* afc_settings); + SWGSimplePTTSettings* getSimplePttSettings(); void setSimplePttSettings(SWGSimplePTTSettings* simple_ptt_settings); @@ -72,6 +76,9 @@ private: qint32 originator_feature_index; bool m_originator_feature_index_isSet; + SWGAFCSettings* afc_settings; + bool m_afc_settings_isSet; + SWGSimplePTTSettings* simple_ptt_settings; bool m_simple_ptt_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 867e0913e..89e7e1df4 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -14,6 +14,9 @@ #define ModelFactory_H_ +#include "SWGAFCActions.h" +#include "SWGAFCReport.h" +#include "SWGAFCSettings.h" #include "SWGAMBEDevice.h" #include "SWGAMBEDevices.h" #include "SWGAMDemodReport.h" @@ -203,6 +206,15 @@ namespace SWGSDRangel { inline void* create(QString type) { + if(QString("SWGAFCActions").compare(type) == 0) { + return new SWGAFCActions(); + } + if(QString("SWGAFCReport").compare(type) == 0) { + return new SWGAFCReport(); + } + if(QString("SWGAFCSettings").compare(type) == 0) { + return new SWGAFCSettings(); + } if(QString("SWGAMBEDevice").compare(type) == 0) { return new SWGAMBEDevice(); } From 1c1eade4088c72fa2a87a7a8dd5c49ea6e26ac7e Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 17 Oct 2020 23:43:20 +0200 Subject: [PATCH 05/27] AFC: settings fix --- plugins/feature/afc/afc.cpp | 86 +++++++----- plugins/feature/afc/afcgui.cpp | 176 ++++++++++++------------- plugins/feature/afc/afcgui.h | 14 +- plugins/feature/afc/afcgui.ui | 198 +++++++++++++++------------- plugins/feature/afc/afcsettings.cpp | 50 +++---- plugins/feature/afc/afcsettings.h | 10 +- plugins/feature/afc/afcworker.cpp | 111 +--------------- plugins/feature/afc/afcworker.h | 3 - 8 files changed, 295 insertions(+), 353 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index 5f33e1a76..54aaba6a9 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -147,10 +147,12 @@ void AFC::applySettings(const AFCSettings& settings, bool force) qDebug() << "AFC::applySettings:" << " m_title: " << settings.m_title << " m_rgbColor: " << settings.m_rgbColor - << " m_rxDeviceSetIndex: " << settings.m_rxDeviceSetIndex - << " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex - << " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs - << " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs + << " m_trackerDeviceSetIndex: " << settings.m_trackerDeviceSetIndex + << " m_trackedDeviceSetIndex: " << settings.m_trackedDeviceSetIndex + << " m_hasTargetFrequency: " << settings.m_hasTargetFrequency + << " m_transverterTarget: " << settings.m_transverterTarget + << " m_targetFrequency: " << settings.m_targetFrequency + << " m_freqTolerance: " << settings.m_freqTolerance << " force: " << force; QList<QString> reverseAPIKeys; @@ -161,17 +163,23 @@ void AFC::applySettings(const AFCSettings& settings, bool force) if ((m_settings.m_rgbColor != settings.m_rgbColor) || force) { reverseAPIKeys.append("rgbColor"); } - if ((m_settings.m_rxDeviceSetIndex != settings.m_rxDeviceSetIndex) || force) { - reverseAPIKeys.append("rxDeviceSetIndex"); + if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { + reverseAPIKeys.append("trackerDeviceSetIndex"); } - if ((m_settings.m_txDeviceSetIndex != settings.m_txDeviceSetIndex) || force) { - reverseAPIKeys.append("txDeviceSetIndex"); + if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) { + reverseAPIKeys.append("trackedDeviceSetIndex"); } - if ((m_settings.m_rx2TxDelayMs != settings.m_rx2TxDelayMs) || force) { - reverseAPIKeys.append("rx2TxDelayMs"); + if ((m_settings.m_hasTargetFrequency != settings.m_hasTargetFrequency) || force) { + reverseAPIKeys.append("hasTargetFrequency"); } - if ((m_settings.m_tx2RxDelayMs != settings.m_tx2RxDelayMs) || force) { - reverseAPIKeys.append("tx2RxDelayMs"); + if ((m_settings.m_transverterTarget != settings.m_transverterTarget) || force) { + reverseAPIKeys.append("transverterTarget"); + } + if ((m_settings.m_targetFrequency != settings.m_targetFrequency) || force) { + reverseAPIKeys.append("targetFrequency"); + } + if ((m_settings.m_freqTolerance != settings.m_freqTolerance) || force) { + reverseAPIKeys.append("freqTolerance"); } AFCWorker::MsgConfigureAFCWorker *msg = AFCWorker::MsgConfigureAFCWorker::create( @@ -292,10 +300,12 @@ void AFC::webapiFormatFeatureSettings( } response.getAfcSettings()->setRgbColor(settings.m_rgbColor); - response.getAfcSettings()->setRxDeviceSetIndex(settings.m_rxDeviceSetIndex); - response.getAfcSettings()->setTxDeviceSetIndex(settings.m_txDeviceSetIndex); - response.getAfcSettings()->setRx2TxDelayMs(settings.m_rx2TxDelayMs); - response.getAfcSettings()->setTx2RxDelayMs(settings.m_tx2RxDelayMs); + response.getAfcSettings()->setTrackerDeviceSetIndex(settings.m_trackerDeviceSetIndex); + response.getAfcSettings()->setTrackedDeviceSetIndex(settings.m_trackedDeviceSetIndex); + response.getAfcSettings()->setHasTargetFrequency(settings.m_hasTargetFrequency); + response.getAfcSettings()->setTransverterTarget(settings.m_transverterTarget); + response.getAfcSettings()->setTargetFrequency(settings.m_targetFrequency); + response.getAfcSettings()->setFreqTolerance(settings.m_freqTolerance); response.getAfcSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); @@ -321,17 +331,23 @@ void AFC::webapiUpdateFeatureSettings( if (featureSettingsKeys.contains("rgbColor")) { settings.m_rgbColor = response.getAfcSettings()->getRgbColor(); } - if (featureSettingsKeys.contains("rxDeviceSetIndex")) { - settings.m_rxDeviceSetIndex = response.getAfcSettings()->getRxDeviceSetIndex(); + if (featureSettingsKeys.contains("trackerDeviceSetIndex")) { + settings.m_trackerDeviceSetIndex = response.getAfcSettings()->getTrackerDeviceSetIndex(); } - if (featureSettingsKeys.contains("txDeviceSetIndex")) { - settings.m_txDeviceSetIndex = response.getAfcSettings()->getTxDeviceSetIndex(); + if (featureSettingsKeys.contains("trackedDeviceSetIndex")) { + settings.m_trackedDeviceSetIndex = response.getAfcSettings()->getTrackedDeviceSetIndex(); } - if (featureSettingsKeys.contains("rx2TxDelayMs")) { - settings.m_rx2TxDelayMs = response.getAfcSettings()->getRx2TxDelayMs(); + if (featureSettingsKeys.contains("hasTargetFrequency")) { + settings.m_hasTargetFrequency = response.getAfcSettings()->getHasTargetFrequency() != 0; } - if (featureSettingsKeys.contains("tx2RxDelayMs")) { - settings.m_tx2RxDelayMs = response.getAfcSettings()->getTx2RxDelayMs(); + if (featureSettingsKeys.contains("hasTargetFrequency")) { + settings.m_hasTargetFrequency = response.getAfcSettings()->getHasTargetFrequency() != 0; + } + if (featureSettingsKeys.contains("targetFrequency")) { + settings.m_targetFrequency = response.getAfcSettings()->getTargetFrequency(); + } + if (featureSettingsKeys.contains("freqTolerance")) { + settings.m_freqTolerance = response.getAfcSettings()->getFreqTolerance(); } if (featureSettingsKeys.contains("useReverseAPI")) { settings.m_useReverseAPI = response.getAfcSettings()->getUseReverseApi() != 0; @@ -372,17 +388,23 @@ void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const A if (channelSettingsKeys.contains("rgbColor") || force) { swgAFCSettings->setRgbColor(settings.m_rgbColor); } - if (channelSettingsKeys.contains("rxDeviceSetIndex") || force) { - swgAFCSettings->setRxDeviceSetIndex(settings.m_rxDeviceSetIndex); + if (channelSettingsKeys.contains("trackerDeviceSetIndex") || force) { + swgAFCSettings->setTrackerDeviceSetIndex(settings.m_trackerDeviceSetIndex); } - if (channelSettingsKeys.contains("txDeviceSetIndex") || force) { - swgAFCSettings->setTxDeviceSetIndex(settings.m_txDeviceSetIndex); + if (channelSettingsKeys.contains("trackedDeviceSetIndex") || force) { + swgAFCSettings->setTrackedDeviceSetIndex(settings.m_trackedDeviceSetIndex); } - if (channelSettingsKeys.contains("rx2TxDelayMs") || force) { - swgAFCSettings->setRx2TxDelayMs(settings.m_rx2TxDelayMs); + if (channelSettingsKeys.contains("hasTargetFrequency") || force) { + swgAFCSettings->setHasTargetFrequency(settings.m_hasTargetFrequency ? 1 : 0); } - if (channelSettingsKeys.contains("tx2RxDelayMs") || force) { - swgAFCSettings->setTx2RxDelayMs(settings.m_tx2RxDelayMs); + if (channelSettingsKeys.contains("targetFrequency") || force) { + swgAFCSettings->setTargetFrequency(settings.m_targetFrequency ? 1 : 0); + } + if (channelSettingsKeys.contains("targetFrequency") || force) { + swgAFCSettings->setTargetFrequency(settings.m_targetFrequency); + } + if (channelSettingsKeys.contains("freqTolerance") || force) { + swgAFCSettings->setFreqTolerance(settings.m_freqTolerance); } QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings") diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index 9d7ae8353..cba3a803d 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -18,8 +18,9 @@ #include <QMessageBox> #include "feature/featureuiset.h" -#include "gui/basicfeaturesettingsdialog.h" #include "device/deviceset.h" +#include "channel/channelapi.h" +#include "gui/basicfeaturesettingsdialog.h" #include "maincore.h" #include "ui_afcgui.h" @@ -89,17 +90,6 @@ bool AFCGUI::handleMessage(const Message& message) return true; } - else if (AFC::MsgPTT::match(message)) - { - qDebug("AFCGUI::handleMessage: AFC::MsgPTT"); - const AFC::MsgPTT& cfg = (AFC::MsgPTT&) message; - bool ptt = cfg.getTx(); - blockApplySettings(true); - ui->ptt->setChecked(ptt); - blockApplySettings(false); - - return true; - } return false; } @@ -132,10 +122,17 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); + + ui->targetFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->targetFrequency->setValueRange(11, 0, 99999999999L); + + ui->toleranceFrequency->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); + ui->toleranceFrequency->setValueRange(5, 0, 99999L); + setChannelWidget(false); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); - m_simplePTT = reinterpret_cast<AFC*>(feature); - m_simplePTT->setMessageQueueToGUI(&m_inputMessageQueue); + m_afc = reinterpret_cast<AFC*>(feature); + m_afc->setMessageQueueToGUI(&m_inputMessageQueue); m_featureUISet->addRollupWidget(this); @@ -173,8 +170,10 @@ void AFCGUI::displaySettings() setTitleColor(m_settings.m_rgbColor); setWindowTitle(m_settings.m_title); blockApplySettings(true); - ui->rxtxDelay->setValue(m_settings.m_rx2TxDelayMs); - ui->txrxDelay->setValue(m_settings.m_tx2RxDelayMs); + ui->hasTargetFrequency->setChecked(m_settings.m_hasTargetFrequency); + ui->transverterTarget->setChecked(m_settings.m_transverterTarget); + ui->targetFrequency->setValue(m_settings.m_targetFrequency); + ui->toleranceFrequency->setValue(m_settings.m_freqTolerance); blockApplySettings(false); } @@ -184,77 +183,74 @@ void AFCGUI::updateDeviceSetLists() std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets(); std::vector<DeviceSet*>::const_iterator it = deviceSets.begin(); - ui->rxDevice->blockSignals(true); - ui->txDevice->blockSignals(true); + ui->trackerDevice->blockSignals(true); + ui->trackedDevice->blockSignals(true); + + ui->trackerDevice->clear(); + ui->trackedDevice->clear(); - ui->rxDevice->clear(); - ui->txDevice->clear(); unsigned int deviceIndex = 0; - unsigned int rxIndex = 0; - unsigned int txIndex = 0; for (; it != deviceSets.end(); ++it, deviceIndex++) { DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine; DSPDeviceSinkEngine *deviceSinkEngine = (*it)->m_deviceSinkEngine; - if (deviceSourceEngine) - { - ui->rxDevice->addItem(QString("R%1").arg(deviceIndex), deviceIndex); - rxIndex++; + if (deviceSourceEngine) { + ui->trackedDevice->addItem(QString("R%1").arg(deviceIndex), deviceIndex); + } else if (deviceSinkEngine) { + ui->trackedDevice->addItem(QString("T%1").arg(deviceIndex), deviceIndex); } - else if (deviceSinkEngine) + + for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++) { - ui->txDevice->addItem(QString("T%1").arg(deviceIndex), deviceIndex); - txIndex++; + ChannelAPI *channel = (*it)->getChannelAt(chi); + + if (channel->getURI() == "sdrangel.channel.freqtracker") + { + ui->trackerDevice->addItem(QString("R%1").arg(deviceIndex), deviceIndex); + break; + } } } - int rxDeviceIndex; - int txDeviceIndex; + int trackedDeviceIndex; + int trackerDeviceIndex; - if (rxIndex > 0) + if (deviceIndex > 0) { - if (m_settings.m_rxDeviceSetIndex < 0) { - ui->rxDevice->setCurrentIndex(0); + if (m_settings.m_trackedDeviceSetIndex < 0) { + ui->trackedDevice->setCurrentIndex(0); } else { - ui->rxDevice->setCurrentIndex(m_settings.m_rxDeviceSetIndex); + ui->trackedDevice->setCurrentIndex(m_settings.m_trackedDeviceSetIndex); } - rxDeviceIndex = ui->rxDevice->currentData().toInt(); + if (m_settings.m_trackerDeviceSetIndex < 0) { + ui->trackerDevice->setCurrentIndex(0); + } else { + ui->trackerDevice->setCurrentIndex(m_settings.m_trackerDeviceSetIndex); + } + + trackedDeviceIndex = ui->trackedDevice->currentData().toInt(); + trackerDeviceIndex = ui->trackerDevice->currentData().toInt(); } else { - rxDeviceIndex = -1; + trackedDeviceIndex = -1; + trackerDeviceIndex = -1; } - - if (txIndex > 0) + if ((trackedDeviceIndex != m_settings.m_trackedDeviceSetIndex) || + (trackerDeviceIndex != m_settings.m_trackerDeviceSetIndex)) { - if (m_settings.m_txDeviceSetIndex < 0) { - ui->txDevice->setCurrentIndex(0); - } else { - ui->txDevice->setCurrentIndex(m_settings.m_txDeviceSetIndex); - } - - txDeviceIndex = ui->txDevice->currentData().toInt(); - } - else - { - txDeviceIndex = -1; - } - - if ((rxDeviceIndex != m_settings.m_rxDeviceSetIndex) || - (txDeviceIndex != m_settings.m_txDeviceSetIndex)) - { - qDebug("AFCGUI::updateDeviceSetLists: device index changed: %d:%d", rxDeviceIndex, txDeviceIndex); - m_settings.m_rxDeviceSetIndex = rxDeviceIndex; - m_settings.m_txDeviceSetIndex = txDeviceIndex; + qDebug("AFCGUI::updateDeviceSetLists: device index changed: %d:%d", trackerDeviceIndex, trackedDeviceIndex); + m_settings.m_trackerDeviceSetIndex = trackerDeviceIndex; + m_settings.m_trackedDeviceSetIndex = trackedDeviceIndex; applySettings(); } - ui->rxDevice->blockSignals(false); - ui->txDevice->blockSignals(false); + ui->trackerDevice->blockSignals(false); + ui->trackedDevice->blockSignals(false); } void AFCGUI::leaveEvent(QEvent*) @@ -303,7 +299,7 @@ void AFCGUI::on_startStop_toggled(bool checked) if (m_doApplySettings) { AFC::MsgStartStop *message = AFC::MsgStartStop::create(checked); - m_simplePTT->getInputMessageQueue()->push(message); + m_afc->getInputMessageQueue()->push(message); } } @@ -313,45 +309,52 @@ void AFCGUI::on_devicesRefresh_clicked() displaySettings(); } -void AFCGUI::on_rxDevice_currentIndexChanged(int index) +void AFCGUI::on_hasTargetFrequency_toggled(bool checked) +{ + m_settings.m_hasTargetFrequency = checked; + applySettings(); +} + +void AFCGUI::on_targetFrequency_changed(quint64 value) +{ + m_settings.m_targetFrequency = value; + applySettings(); +} + +void AFCGUI::on_transverterTarget_toggled(bool checked) +{ + m_settings.m_transverterTarget = checked; + applySettings(); +} + +void AFCGUI::on_trackerDevice_currentIndexChanged(int index) { if (index >= 0) { - m_settings.m_rxDeviceSetIndex = index; + m_settings.m_trackerDeviceSetIndex = index; applySettings(); } } -void AFCGUI::on_txDevice_currentIndexChanged(int index) +void AFCGUI::on_trackedDevice_currentIndexChanged(int index) { if (index >= 0) { - m_settings.m_txDeviceSetIndex = index; + m_settings.m_trackedDeviceSetIndex = index; applySettings(); } - } -void AFCGUI::on_rxtxDelay_valueChanged(int value) + +void AFCGUI::on_toleranceFrequency_changed(quint64 value) { - m_settings.m_rx2TxDelayMs = value; + m_settings.m_freqTolerance = value; applySettings(); } -void AFCGUI::on_txrxDelay_valueChanged(int value) -{ - m_settings.m_tx2RxDelayMs = value; - applySettings(); -} - -void AFCGUI::on_ptt_toggled(bool checked) -{ - applyPTT(checked); -} - void AFCGUI::updateStatus() { - int state = m_simplePTT->getState(); + int state = m_afc->getState(); if (m_lastFeatureState != state) { @@ -368,7 +371,7 @@ void AFCGUI::updateStatus() break; case Feature::StError: ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); - QMessageBox::information(this, tr("Message"), m_simplePTT->getErrorMessage()); + QMessageBox::information(this, tr("Message"), m_afc->getErrorMessage()); break; default: break; @@ -383,15 +386,6 @@ void AFCGUI::applySettings(bool force) if (m_doApplySettings) { AFC::MsgConfigureAFC* message = AFC::MsgConfigureAFC::create( m_settings, force); - m_simplePTT->getInputMessageQueue()->push(message); - } -} - -void AFCGUI::applyPTT(bool tx) -{ - if (m_doApplySettings) - { - AFC::MsgPTT* message = AFC::MsgPTT::create(tx); - m_simplePTT->getInputMessageQueue()->push(message); + m_afc->getInputMessageQueue()->push(message); } } diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index 0faa09d7d..7b04f6382 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -50,7 +50,7 @@ private: AFCSettings m_settings; bool m_doApplySettings; - AFC* m_simplePTT; + AFC* m_afc; MessageQueue m_inputMessageQueue; QTimer m_statusTimer; int m_lastFeatureState; @@ -62,7 +62,6 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); - void applyPTT(bool tx); void displaySettings(); void updateDeviceSetLists(); bool handleMessage(const Message& message); @@ -75,12 +74,13 @@ private slots: void onWidgetRolled(QWidget* widget, bool rollDown); void handleInputMessages(); void on_startStop_toggled(bool checked); + void on_hasTargetFrequency_toggled(bool checked); void on_devicesRefresh_clicked(); - void on_rxDevice_currentIndexChanged(int index); - void on_txDevice_currentIndexChanged(int index); - void on_rxtxDelay_valueChanged(int value); - void on_txrxDelay_valueChanged(int value); - void on_ptt_toggled(bool checked); + void on_transverterTarget_toggled(bool checked); + void on_targetFrequency_changed(quint64 value); + void on_trackerDevice_currentIndexChanged(int index); + void on_trackedDevice_currentIndexChanged(int index); + void on_toleranceFrequency_changed(quint64 value); void updateStatus(); }; diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui index d11eb6964..bfbef1f4c 100644 --- a/plugins/feature/afc/afcgui.ui +++ b/plugins/feature/afc/afcgui.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>320</width> + <width>340</width> <height>181</height> </rect> </property> @@ -18,16 +18,10 @@ </property> <property name="minimumSize"> <size> - <width>320</width> + <width>340</width> <height>100</height> </size> </property> - <property name="maximumSize"> - <size> - <width>320</width> - <height>16777215</height> - </size> - </property> <property name="font"> <font> <family>Liberation Sans</family> @@ -42,7 +36,7 @@ <rect> <x>10</x> <y>10</y> - <width>301</width> + <width>311</width> <height>151</height> </rect> </property> @@ -66,7 +60,7 @@ <number>2</number> </property> <item> - <layout class="QHBoxLayout" name="pttLayout"> + <layout class="QHBoxLayout" name="mainLayout"> <item> <widget class="ButtonSwitch" name="startStop"> <property name="toolTip"> @@ -83,30 +77,17 @@ </widget> </item> <item> - <widget class="ButtonSwitch" name="ptt"> - <property name="minimumSize"> - <size> - <width>200</width> - <height>50</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>20</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> + <widget class="ButtonSwitch" name="hasTargetFrequency"> <property name="toolTip"> - <string>Push To Talk</string> + <string>Adjust device frequency to match tracker frequency</string> </property> <property name="text"> - <string>PTT</string> + <string>T</string> </property> </widget> </item> <item> - <widget class="QLabel" name="statusIndicator"> + <widget class="ValueDial" name="targetFrequency" native="true"> <property name="sizePolicy"> <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> <horstretch>0</horstretch> @@ -115,25 +96,48 @@ </property> <property name="minimumSize"> <size> - <width>24</width> - <height>24</height> + <width>32</width> + <height>16</height> </size> </property> - <property name="toolTip"> - <string>Idle</string> + <property name="font"> + <font> + <family>Liberation Mono</family> + <pointsize>12</pointsize> + </font> </property> - <property name="styleSheet"> - <string notr="true">QLabel { background-color: gray; border-radius: 12px; }</string> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Tracker frequency in Hz</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="targetFrequencyUnits"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + <item> + <widget class="ButtonSwitch" name="transverterTarget"> + <property name="toolTip"> + <string>Use transverter or device frequency for tracker frequency adjustment</string> </property> <property name="text"> - <string/> + <string>X</string> </property> </widget> </item> </layout> </item> <item> - <layout class="QHBoxLayout" name="localDeviceLayout"> + <layout class="QHBoxLayout" name="devicesLayout"> <item> <widget class="QPushButton" name="devicesRefresh"> <property name="maximumSize"> @@ -155,14 +159,14 @@ </widget> </item> <item> - <widget class="QLabel" name="rxDeviceLabel"> + <widget class="QLabel" name="trackerLabel"> <property name="text"> - <string>Rx dev</string> + <string>Tracker</string> </property> </widget> </item> <item> - <widget class="QComboBox" name="rxDevice"> + <widget class="QComboBox" name="trackerDevice"> <property name="minimumSize"> <size> <width>55</width> @@ -176,7 +180,7 @@ </size> </property> <property name="toolTip"> - <string>Receiver deviceset index</string> + <string>Tracker deviceset index</string> </property> </widget> </item> @@ -194,14 +198,14 @@ </spacer> </item> <item> - <widget class="QLabel" name="txDeviceLabel"> + <widget class="QLabel" name="trackedLabel"> <property name="text"> - <string>Tx dev</string> + <string>Tracked</string> </property> </widget> </item> <item> - <widget class="QComboBox" name="txDevice"> + <widget class="QComboBox" name="trackedDevice"> <property name="minimumSize"> <size> <width>55</width> @@ -215,7 +219,7 @@ </size> </property> <property name="toolTip"> - <string>Transmitter deviceset index</string> + <string>Tracked deviceset index</string> </property> </widget> </item> @@ -224,32 +228,50 @@ <item> <layout class="QHBoxLayout" name="DelaysLayout"> <item> - <widget class="QLabel" name="rxtxDelayLabel"> - <property name="text"> - <string>Rx-Tx </string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="rxtxDelay"> + <widget class="QLabel" name="toleranceLabel"> <property name="toolTip"> - <string>Rx to Tx transition delay (ms)</string> + <string/> </property> - <property name="minimum"> - <number>100</number> - </property> - <property name="maximum"> - <number>5000</number> - </property> - <property name="singleStep"> - <number>100</number> + <property name="text"> + <string>Tol</string> </property> </widget> </item> <item> - <widget class="QLabel" name="rxtxDelayUnits"> + <widget class="ValueDial" name="toleranceFrequency" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>16</height> + </size> + </property> + <property name="font"> + <font> + <family>Liberation Mono</family> + <pointsize>12</pointsize> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Frequency tolerance before device frequency is changed (Hz)</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="toleranceUnits"> <property name="text"> - <string>ms</string> + <string>Hz</string> </property> </widget> </item> @@ -267,36 +289,28 @@ </spacer> </item> <item> - <widget class="QLabel" name="txrxDelayLabel"> + <widget class="QLabel" name="statusIndicator"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> <property name="toolTip"> + <string>Idle</string> + </property> + <property name="styleSheet"> + <string notr="true">QLabel { background-color: gray; border-radius: 8px; }</string> + </property> + <property name="text"> <string/> </property> - <property name="text"> - <string>Tx-Rx</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="txrxDelay"> - <property name="toolTip"> - <string>Tx to Rx transition delay (ms)</string> - </property> - <property name="minimum"> - <number>100</number> - </property> - <property name="maximum"> - <number>5000</number> - </property> - <property name="singleStep"> - <number>100</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="txrxDelayUnits"> - <property name="text"> - <string>ms</string> - </property> </widget> </item> </layout> @@ -316,6 +330,12 @@ <extends>QToolButton</extends> <header>gui/buttonswitch.h</header> </customwidget> + <customwidget> + <class>ValueDial</class> + <extends>QWidget</extends> + <header>gui/valuedial.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources> <include location="../../../sdrgui/resources/res.qrc"/> diff --git a/plugins/feature/afc/afcsettings.cpp b/plugins/feature/afc/afcsettings.cpp index 8ab695009..4ca1bf8c4 100644 --- a/plugins/feature/afc/afcsettings.cpp +++ b/plugins/feature/afc/afcsettings.cpp @@ -31,10 +31,12 @@ void AFCSettings::resetToDefaults() { m_title = "AFC"; m_rgbColor = QColor(255, 255, 0).rgb(); - m_rxDeviceSetIndex = -1; - m_txDeviceSetIndex = -1; - m_rx2TxDelayMs = 100; - m_tx2RxDelayMs = 100; + m_trackerDeviceSetIndex = -1; + m_trackedDeviceSetIndex = -1; + m_hasTargetFrequency = false; + m_transverterTarget = false; + m_targetFrequency = 0; + m_freqTolerance = 1000; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; m_reverseAPIPort = 8888; @@ -48,15 +50,17 @@ QByteArray AFCSettings::serialize() const s.writeString(1, m_title); s.writeU32(2, m_rgbColor); - s.writeS32(3, m_rxDeviceSetIndex); - s.writeS32(4, m_txDeviceSetIndex); - s.writeU32(5, m_rx2TxDelayMs); - s.writeU32(6, m_tx2RxDelayMs); - s.writeBool(7, m_useReverseAPI); - s.writeString(8, m_reverseAPIAddress); - s.writeU32(9, m_reverseAPIPort); - s.writeU32(10, m_reverseAPIFeatureSetIndex); - s.writeU32(11, m_reverseAPIFeatureIndex); + s.writeS32(3, m_trackerDeviceSetIndex); + s.writeS32(5, m_trackedDeviceSetIndex); + s.writeBool(6, m_hasTargetFrequency); + s.writeBool(7, m_transverterTarget); + s.writeU64(8, m_targetFrequency); + s.writeU64(9, m_freqTolerance); + s.writeBool(10, m_useReverseAPI); + s.writeString(11, m_reverseAPIAddress); + s.writeU32(12, m_reverseAPIPort); + s.writeU32(13, m_reverseAPIFeatureSetIndex); + s.writeU32(14, m_reverseAPIFeatureIndex); return s.final(); } @@ -80,13 +84,15 @@ bool AFCSettings::deserialize(const QByteArray& data) d.readString(1, &m_title, "AFC"); d.readU32(2, &m_rgbColor, QColor(255, 255, 0).rgb()); - d.readS32(3, &m_rxDeviceSetIndex, -1); - d.readS32(4, &m_txDeviceSetIndex, -1); - d.readU32(5, &m_rx2TxDelayMs, 100); - d.readU32(6, &m_tx2RxDelayMs, 100); - d.readBool(7, &m_useReverseAPI, false); - d.readString(8, &m_reverseAPIAddress, "127.0.0.1"); - d.readU32(9, &utmp, 0); + d.readS32(3, &m_trackerDeviceSetIndex, -1); + d.readS32(5, &m_trackedDeviceSetIndex, -1); + d.readBool(6, &m_hasTargetFrequency, false); + d.readBool(7, &m_transverterTarget, false); + d.readU64(8, &m_targetFrequency, 0); + d.readU64(9, &m_freqTolerance, 1000); + d.readBool(10, &m_useReverseAPI, false); + d.readString(11, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(12, &utmp, 0); if ((utmp > 1023) && (utmp < 65535)) { m_reverseAPIPort = utmp; @@ -94,9 +100,9 @@ bool AFCSettings::deserialize(const QByteArray& data) m_reverseAPIPort = 8888; } - d.readU32(10, &utmp, 0); + d.readU32(13, &utmp, 0); m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp; - d.readU32(11, &utmp, 0); + d.readU32(14, &utmp, 0); m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp; return true; diff --git a/plugins/feature/afc/afcsettings.h b/plugins/feature/afc/afcsettings.h index 8dcf0c8b1..e633e612f 100644 --- a/plugins/feature/afc/afcsettings.h +++ b/plugins/feature/afc/afcsettings.h @@ -27,10 +27,12 @@ struct AFCSettings { QString m_title; quint32 m_rgbColor; - int m_rxDeviceSetIndex; - int m_txDeviceSetIndex; - unsigned int m_rx2TxDelayMs; - unsigned int m_tx2RxDelayMs; + int m_trackerDeviceSetIndex; //!< will take the first instance of freq tracker in the list of channels + int m_trackedDeviceSetIndex; + bool m_hasTargetFrequency; + bool m_transverterTarget; + quint64 m_targetFrequency; + quint64 m_freqTolerance; bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort; diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index 1891b4a77..dfd7fb339 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -37,7 +37,6 @@ AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_mutex(QMutex::Recursive) { qDebug("AFCWorker::AFCWorker"); - connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); } AFCWorker::~AFCWorker() @@ -90,15 +89,6 @@ bool AFCWorker::handleMessage(const Message& cmd) return true; } - else if (MsgPTT::match(cmd)) - { - MsgPTT& cfg = (MsgPTT&) cmd; - qDebug() << "AFCWorker::handleMessage: MsgPTT"; - - sendPTT(cfg.getTx()); - - return true; - } else { return false; @@ -110,101 +100,12 @@ void AFCWorker::applySettings(const AFCSettings& settings, bool force) qDebug() << "AFCWorker::applySettings:" << " m_title: " << settings.m_title << " m_rgbColor: " << settings.m_rgbColor - << " m_rxDeviceSetIndex: " << settings.m_rxDeviceSetIndex - << " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex - << " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs - << " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs + << " m_trackerDeviceSetIndex: " << settings.m_trackerDeviceSetIndex + << " m_trackedDeviceSetIndex: " << settings.m_trackedDeviceSetIndex + << " m_hasTargetFrequency: " << settings.m_hasTargetFrequency + << " m_transverterTarget: " << settings.m_transverterTarget + << " m_targetFrequency: " << settings.m_targetFrequency + << " m_freqTolerance: " << settings.m_freqTolerance << " force: " << force; m_settings = settings; } - -void AFCWorker::sendPTT(bool tx) -{ - if (!m_updateTimer.isActive()) - { - bool switchedOff = false; - m_mutex.lock(); - - if (tx) - { - if (m_settings.m_rxDeviceSetIndex >= 0) - { - m_tx = false; - switchedOff = turnDevice(false); - } - - if (m_settings.m_txDeviceSetIndex >= 0) - { - m_tx = true; - m_updateTimer.start(m_settings.m_rx2TxDelayMs); - } - } - else - { - if (m_settings.m_txDeviceSetIndex >= 0) - { - m_tx = true; - switchedOff = turnDevice(false); - } - - if (m_settings.m_rxDeviceSetIndex >= 0) - { - m_tx = false; - m_updateTimer.start(m_settings.m_tx2RxDelayMs); - } - } - - if (switchedOff && (m_msgQueueToGUI)) - { - AFCReport::MsgRadioState *msg = AFCReport::MsgRadioState::create(AFCReport::RadioIdle); - m_msgQueueToGUI->push(msg); - } - } -} - -void AFCWorker::updateHardware() -{ - SWGSDRangel::SWGSuccessResponse response; - SWGSDRangel::SWGErrorResponse error; - m_updateTimer.stop(); - m_mutex.unlock(); - - if (turnDevice(true)) - { - m_webAPIAdapterInterface->devicesetFocusPatch( - m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); - - if (m_msgQueueToGUI) - { - AFCReport::MsgRadioState *msg = AFCReport::MsgRadioState::create( - m_tx ? AFCReport::RadioTx : AFCReport::RadioRx - ); - m_msgQueueToGUI->push(msg); - } - } -} - -bool AFCWorker::turnDevice(bool on) -{ - SWGSDRangel::SWGDeviceState response; - SWGSDRangel::SWGErrorResponse error; - int httpCode; - - if (on) { - httpCode = m_webAPIAdapterInterface->devicesetDeviceRunPost( - m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); - } else { - httpCode = m_webAPIAdapterInterface->devicesetDeviceRunDelete( - m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error); - } - - if (httpCode/100 == 2) - { - return true; - } - else - { - qWarning("AFCWorker::turnDevice: error: %s", qPrintable(*error.getMessage())); - return false; - } -} diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index 86ef75b22..bc074bfd4 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -95,12 +95,9 @@ private: bool handleMessage(const Message& cmd); void applySettings(const AFCSettings& settings, bool force = false); - void sendPTT(bool tx); - bool turnDevice(bool on); private slots: void handleInputMessages(); - void updateHardware(); }; #endif // INCLUDE_FEATURE_SIMPLEPTTWORKER_H_ From 977638d9d66bed382d911d24f184c13043357dea Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Thu, 22 Oct 2020 08:38:43 +0200 Subject: [PATCH 06/27] AFC: implemented full functionality --- plugins/feature/afc/afc.cpp | 131 ++++++-- plugins/feature/afc/afc.h | 30 +- plugins/feature/afc/afcgui.ui | 2 +- plugins/feature/afc/afcworker.cpp | 363 +++++++++++++++++++++- plugins/feature/afc/afcworker.h | 62 +++- sdrbase/channel/channelapi.cpp | 13 +- sdrbase/channel/channelapi.h | 9 + sdrbase/feature/feature.cpp | 2 + sdrbase/feature/feature.h | 40 +++ sdrbase/webapi/webapirequestmapper.cpp | 256 ++-------------- sdrbase/webapi/webapiutils.cpp | 408 +++++++++++++++++++++++++ sdrbase/webapi/webapiutils.h | 21 ++ 12 files changed, 1047 insertions(+), 290 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index 54aaba6a9..21801de97 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -25,14 +25,17 @@ #include "SWGFeatureActions.h" #include "SWGAFCReport.h" #include "SWGDeviceState.h" +#include "SWGChannelSettings.h" #include "dsp/dspengine.h" +#include "device/deviceset.h" +#include "channel/channelapi.h" +#include "maincore.h" #include "afcworker.h" #include "afc.h" MESSAGE_CLASS_DEFINITION(AFC::MsgConfigureAFC, Message) -MESSAGE_CLASS_DEFINITION(AFC::MsgPTT, Message) MESSAGE_CLASS_DEFINITION(AFC::MsgStartStop, Message) const QString AFC::m_featureIdURI = "sdrangel.feature.afc"; @@ -40,7 +43,8 @@ const QString AFC::m_featureId = "AFC"; AFC::AFC(WebAPIAdapterInterface *webAPIAdapterInterface) : Feature(m_featureIdURI, webAPIAdapterInterface), - m_ptt(false) + m_trackerDeviceSet(nullptr), + m_trackedDeviceSet(nullptr) { setObjectName(m_featureId); m_worker = new AFCWorker(webAPIAdapterInterface); @@ -55,6 +59,7 @@ AFC::~AFC() } delete m_worker; + removeFeatureReferences(); } void AFC::start() @@ -90,17 +95,6 @@ bool AFC::handleMessage(const Message& cmd) return true; } - else if (MsgPTT::match(cmd)) - { - MsgPTT& cfg = (MsgPTT&) cmd; - m_ptt = cfg.getTx(); - qDebug() << "AFC::handleMessage: MsgPTT: tx:" << m_ptt; - - AFCWorker::MsgPTT *msg = AFCWorker::MsgPTT::create(m_ptt); - m_worker->getInputMessageQueue()->push(msg); - - return true; - } else if (MsgStartStop::match(cmd)) { MsgStartStop& cfg = (MsgStartStop&) cmd; @@ -114,10 +108,25 @@ bool AFC::handleMessage(const Message& cmd) return true; } - else - { - return false; - } + else if (Feature::MsgChannelSettings::match(cmd)) + { + Feature::MsgChannelSettings& cfg = (Feature::MsgChannelSettings&) cmd; + SWGSDRangel::SWGChannelSettings *swgChannelSettings = cfg.getSWGSettings(); + QString *channelType = swgChannelSettings->getChannelType(); + qDebug() << "AFC::handleMessage: Feature::MsgChannelSettings: " << *channelType; + + if (m_worker->isRunning()) + { + m_worker->getInputMessageQueue()->push(&cfg); + } + else + { + delete swgChannelSettings; + return true; + } + } + + return false; } QByteArray AFC::serialize() const @@ -182,6 +191,14 @@ void AFC::applySettings(const AFCSettings& settings, bool force) reverseAPIKeys.append("freqTolerance"); } + if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { + trackerDeviceChange(settings.m_trackerDeviceSetIndex); + } + + if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) { + trackedDeviceChange(settings.m_trackedDeviceSetIndex); + } + AFCWorker::MsgConfigureAFCWorker *msg = AFCWorker::MsgConfigureAFCWorker::create( settings, force ); @@ -266,20 +283,6 @@ int AFC::webapiActionsPost( if (swgAFCActions) { - if (featureActionsKeys.contains("ptt")) - { - bool ptt = swgAFCActions->getPtt() != 0; - - MsgPTT *msg = MsgPTT::create(ptt); - getInputMessageQueue()->push(msg); - - if (getMessageQueueToGUI()) - { - MsgPTT *msgToGUI = MsgPTT::create(ptt); - getMessageQueueToGUI()->push(msgToGUI); - } - } - return 202; } else @@ -368,7 +371,6 @@ void AFC::webapiUpdateFeatureSettings( void AFC::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response) { - response.getAfcReport()->setPtt(m_ptt ? 1 : 0); } void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AFCSettings& settings, bool force) @@ -447,3 +449,68 @@ void AFC::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } + +void AFC::trackerDeviceChange(int deviceIndex) +{ + MainCore *mainCore = MainCore::instance(); + m_trackerDeviceSet = mainCore->getDeviceSets()[deviceIndex]; + + for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); + + if (channel->getURI() == "sdrangel.channel.freqtracker") + { + channel->addFeatureSettingsFeedback(this); + break; + } + } +} + +void AFC::trackedDeviceChange(int deviceIndex) +{ + MainCore *mainCore = MainCore::instance(); + m_trackedDeviceSet = mainCore->getDeviceSets()[deviceIndex]; + + for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); + + if (channel->getURI() != "sdrangel.channel.freqtracker") { + channel->addFeatureSettingsFeedback(this); + } + } +} + +void AFC::removeFeatureReferences() +{ + MainCore *mainCore = MainCore::instance(); + + if ((m_settings.m_trackerDeviceSetIndex >= 0) && (m_settings.m_trackerDeviceSetIndex < mainCore->getDeviceSets().size())) + { + DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackerDeviceSetIndex]; + + if (trackerDeviceSet == m_trackerDeviceSet) + { + for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); + channel->removeFeatureSettingsFeedback(this); + } + } + } + + if ((m_settings.m_trackedDeviceSetIndex >= 0) && (m_settings.m_trackedDeviceSetIndex < mainCore->getDeviceSets().size())) + { + DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackedDeviceSetIndex]; + + if (trackerDeviceSet == m_trackedDeviceSet) + { + for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); + channel->removeFeatureSettingsFeedback(this); + } + } + } +} diff --git a/plugins/feature/afc/afc.h b/plugins/feature/afc/afc.h index 9cdb1afb4..9ac4c1850 100644 --- a/plugins/feature/afc/afc.h +++ b/plugins/feature/afc/afc.h @@ -26,10 +26,11 @@ #include "afcsettings.h" -class WebAPIAdapterInterface; -class AFCWorker; class QNetworkAccessManager; class QNetworkReply; +class WebAPIAdapterInterface; +class DeviceSet; +class AFCWorker; namespace SWGSDRangel { class SWGDeviceState; @@ -61,25 +62,6 @@ public: { } }; - class MsgPTT : public Message { - MESSAGE_CLASS_DECLARATION - - public: - bool getTx() const { return m_tx; } - - static MsgPTT* create(bool tx) { - return new MsgPTT(tx); - } - - private: - bool m_tx; - - MsgPTT(bool tx) : - Message(), - m_tx(tx) - { } - }; - class MsgStartStop : public Message { MESSAGE_CLASS_DECLARATION @@ -150,7 +132,8 @@ private: QThread m_thread; AFCWorker *m_worker; AFCSettings m_settings; - bool m_ptt; + DeviceSet *m_trackerDeviceSet; + DeviceSet *m_trackedDeviceSet; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -160,6 +143,9 @@ private: void applySettings(const AFCSettings& settings, bool force = false); void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AFCSettings& settings, bool force); + void trackerDeviceChange(int deviceIndex); + void trackedDeviceChange(int deviceIndex); + void removeFeatureReferences(); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui index bfbef1f4c..cef53c7ce 100644 --- a/plugins/feature/afc/afcgui.ui +++ b/plugins/feature/afc/afcgui.ui @@ -127,7 +127,7 @@ <item> <widget class="ButtonSwitch" name="transverterTarget"> <property name="toolTip"> - <string>Use transverter or device frequency for tracker frequency adjustment</string> + <string>Use transverter frequency for tracker frequency adjustment</string> </property> <property name="text"> <string>X</string> diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index dfd7fb339..c4471181c 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -19,21 +19,31 @@ #include "SWGDeviceState.h" #include "SWGSuccessResponse.h" +#include "SWGDeviceSettings.h" +#include "SWGChannelSettings.h" #include "SWGErrorResponse.h" #include "webapi/webapiadapterinterface.h" +#include "webapi/webapiutils.h" +#include "device/deviceset.h" +#include "device/deviceapi.h" +#include "channel/channelapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "afcreport.h" #include "afcworker.h" MESSAGE_CLASS_DEFINITION(AFCWorker::MsgConfigureAFCWorker, Message) -MESSAGE_CLASS_DEFINITION(AFCWorker::MsgPTT, Message) +MESSAGE_CLASS_DEFINITION(AFCWorker::MsgTrackedDeviceChange, Message) AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_webAPIAdapterInterface(webAPIAdapterInterface), m_msgQueueToGUI(nullptr), m_running(false), - m_tx(false), + m_freqTracker(nullptr), + m_trackerDeviceFrequency(0), + m_trackerChannelOffset(0), m_mutex(QMutex::Recursive) { qDebug("AFCWorker::AFCWorker"); @@ -81,14 +91,25 @@ bool AFCWorker::handleMessage(const Message& cmd) { if (MsgConfigureAFCWorker::match(cmd)) { + qDebug() << "AFCWorker::handleMessage: MsgConfigureAFCWorker"; QMutexLocker mutexLocker(&m_mutex); MsgConfigureAFCWorker& cfg = (MsgConfigureAFCWorker&) cmd; - qDebug() << "AFCWorker::handleMessage: MsgConfigureAFCWorker"; applySettings(cfg.getSettings(), cfg.getForce()); return true; } + else if (Feature::MsgChannelSettings::match(cmd)) + { + qDebug() << "AFCWorker::handleMessage: Feature::MsgChannelSettings"; + QMutexLocker mutexLocker(&m_mutex); + Feature::MsgChannelSettings& cfg = (Feature::MsgChannelSettings&) cmd; + SWGSDRangel::SWGChannelSettings *swgChannelSettings = cfg.getSWGSettings(); + processChannelSettings(cfg.getChannelAPI(), cfg.getChannelSettingsKeys(), swgChannelSettings); + + delete swgChannelSettings; + return true; + } else { return false; @@ -107,5 +128,341 @@ void AFCWorker::applySettings(const AFCSettings& settings, bool force) << " m_targetFrequency: " << settings.m_targetFrequency << " m_freqTolerance: " << settings.m_freqTolerance << " force: " << force; + + if ((settings.m_trackerDeviceSetIndex != m_settings.m_trackerDeviceSetIndex) || force) { + initTrackerDeviceSet(settings.m_trackerDeviceSetIndex); + } + + if ((settings.m_trackedDeviceSetIndex != m_settings.m_trackedDeviceSetIndex) || force) { + initTrackedDeviceSet(settings.m_trackedDeviceSetIndex); + } + m_settings = settings; } + + +void AFCWorker::initTrackerDeviceSet(int deviceSetIndex) +{ + MainCore *mainCore = MainCore::instance(); + m_trackerDeviceSet = mainCore->getDeviceSets()[deviceSetIndex]; + + for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); + + if (channel->getURI() == "sdrangel.channel.freqtracker") + { + m_freqTracker = channel; + SWGSDRangel::SWGDeviceSettings resDevice; + SWGSDRangel::SWGChannelSettings resChannel; + SWGSDRangel::SWGErrorResponse error; + + int rc = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(deviceSetIndex, resDevice, error); + + if (rc / 100 == 2) + { + QJsonObject *jsonObj = resDevice.asJsonObject(); + QJsonValue freqValue; + + if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", freqValue)) + { + double freq = freqValue.toDouble(); + m_trackerDeviceFrequency = freq; + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device frequency"; + } + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); + } + + + rc = m_webAPIAdapterInterface->devicesetChannelSettingsGet(deviceSetIndex, i, resChannel, error); + + if (rc / 100 == 2) { + m_trackerChannelOffset = resChannel.getFreqTrackerSettings()->getInputFrequencyOffset(); + } else { + qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetChannelSettingsGet error" << rc << ":" << *error.getMessage(); + } + + break; + } + } +} + +void AFCWorker::initTrackedDeviceSet(int deviceSetIndex) +{ + MainCore *mainCore = MainCore::instance(); + m_trackedDeviceSet = mainCore->getDeviceSets()[deviceSetIndex]; + m_channelsMap.clear(); + + for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) + { + ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); + + if (channel->getURI() != "sdrangel.channel.freqtracker") + { + SWGSDRangel::SWGChannelSettings resChannel; + SWGSDRangel::SWGErrorResponse error; + + int rc = m_webAPIAdapterInterface->devicesetChannelSettingsGet(deviceSetIndex, i, resChannel, error); + + if (rc / 100 == 2) + { + QJsonObject *jsonObj = resChannel.asJsonObject(); + QJsonValue directionValue; + QJsonValue channelOffsetValue; + + if (WebAPIUtils::extractValue(*jsonObj, "direction", directionValue)) + { + int direction = directionValue.toInt(); + + if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) + { + int channelOffset = channelOffsetValue.toInt(); + m_channelsMap.insert(channel, ChannelTracking{channelOffset, m_trackerChannelOffset, direction}); + } + else + { + qDebug() << "AFCWorker::initTrackedDeviceSet: cannot find channel offset frequency"; + } + } + else + { + qDebug() << "AFCWorker::initTrackedDeviceSet: cannot find channel direction"; + } + } + else + { + qDebug() << "AFCWorker::initTrackedDeviceSet: devicesetChannelSettingsGet error" << rc << ":" << *error.getMessage(); + } + } + } +} + +void AFCWorker::processChannelSettings( + const ChannelAPI *channelAPI, + const QList<QString> &channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings) +{ + MainCore *mainCore = MainCore::instance(); + + if (*swgChannelSettings->getChannelType() == "FreqTracker") + { + m_trackerChannelOffset = swgChannelSettings->getFreqTrackerSettings()->getInputFrequencyOffset(); + QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); + + for (; it != m_channelsMap.end(); ++it) + { + if (mainCore->existsChannel(it.key())) + { + int channelOffset = it.value().m_channelOffset + m_trackerChannelOffset - it.value().m_trackerOffset; + updateChannelOffset(it.key(),it.value().m_channelDirection, channelOffset); + } + else + { + m_channelsMap.erase(it); + } + } + + if (m_settings.m_hasTargetFrequency) { + updateTarget(); + } + } + else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) + { + QJsonObject *jsonObj = swgChannelSettings->asJsonObject(); + QJsonValue channelOffsetValue; + + if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) + { + int channelOffset = channelOffsetValue.toInt(); + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; + } + } +} + +void AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset) +{ + SWGSDRangel::SWGChannelSettings swgChannelSettings; + SWGSDRangel::SWGErrorResponse errorResponse; + QString channelId; + channelAPI->getIdentifier(channelId); + swgChannelSettings.init(); + qDebug() << "AFCWorker::updateChannelOffset:" << channelId << ":" << offset; + + QStringList channelSettingsKeys; + channelSettingsKeys.append("inputFrequencyOffset"); + QString jsonSettingsStr = tr("\"inputFrequencyOffset\":%1").arg(offset); + + QString jsonStr = tr("{ \"channelType\": \"%1\", \"direction\": \"%2\", \"%3Settings\": {%4}}") + .arg(QString(channelId)) + .arg(direction) + .arg(QString(channelId)) + .arg(jsonSettingsStr); + swgChannelSettings.fromJson(jsonStr); + + int httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch( + m_trackedDeviceSet->getIndex(), + channelAPI->getIndexInDeviceSet(), + false, // PATCH + channelSettingsKeys, + swgChannelSettings, + errorResponse + ); + + if (httpRC / 100 != 2) { + qDebug() << "AFCWorker::updateChannelOffset: error code" << httpRC << ":" << *errorResponse.getMessage(); + } +} + +void AFCWorker::updateTarget() +{ + SWGSDRangel::SWGDeviceSettings resDevice; + SWGSDRangel::SWGChannelSettings resChannel; + SWGSDRangel::SWGErrorResponse error; + + int rc = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(m_settings.m_trackerDeviceSetIndex, resDevice, error); + + if (rc / 100 == 2) + { + QJsonObject *jsonObj = resDevice.asJsonObject(); + QJsonValue freqValue; + + if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", freqValue)) + { + double freq = freqValue.toDouble(); + m_trackerDeviceFrequency = freq; + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device frequency"; + return; + } + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); + return; + } + + int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; + int64_t correction = m_settings.m_targetFrequency - trackerFrequency; + int64_t tolerance = m_settings.m_freqTolerance; + qDebug() << "AFCWorker::initTrackerDeviceSet: correction:" << correction << "tolerance:" << tolerance; + + if ((correction > -tolerance) && (correction < tolerance)) { + return; + } + + if (m_settings.m_transverterTarget) // act on transverter + { + QJsonObject *jsonObj = resDevice.asJsonObject(); + QJsonValue xverterFrequencyValue; + + if (WebAPIUtils::extractValue(*jsonObj, "transverterDeltaFrequency", xverterFrequencyValue)) + { + double xverterFrequency = xverterFrequencyValue.toDouble(); + updateDeviceFrequency(m_trackerDeviceSet, "transverterDeltaFrequency", xverterFrequency + correction); + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; + return; + } + } + else // act on device + { + QJsonObject *jsonObj = resDevice.asJsonObject(); + QJsonValue deviceFrequencyValue; + + if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", deviceFrequencyValue)) + { + double deviceFrequency = deviceFrequencyValue.toDouble(); + updateDeviceFrequency(m_trackerDeviceSet, "centerFrequency", deviceFrequency + correction); + } + else + { + qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; + return; + } + } +} + +bool AFCWorker::updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency) +{ + SWGSDRangel::SWGDeviceSettings swgDeviceSettings; + SWGSDRangel::SWGErrorResponse errorResponse; + QStringList deviceSettingsKeys; + deviceSettingsKeys.append(key); + int deviceIndex = deviceSet->getIndex(); + DeviceAPI *deviceAPI = deviceSet->m_deviceAPI; + swgDeviceSettings.init(); + QString jsonSettingsStr = tr("\"%1\":%2").arg(key).arg(frequency); + QString deviceSettingsKey; + getDeviceSettingsKey(deviceAPI, deviceSettingsKey); + + QString jsonStr = tr("{ \"deviceHwType\": \"%1\", \"direction\": \"%2\", \"%3\": {%4}}") + .arg(deviceAPI->getHardwareId()) + .arg(getDeviceDirection(deviceAPI)) + .arg(deviceSettingsKey) + .arg(jsonSettingsStr); + swgDeviceSettings.fromJson(jsonStr); + qDebug() << "AFCWorker::updateDeviceFrequency:" << jsonStr; + + int httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch + ( + deviceIndex, + false, // PATCH + deviceSettingsKeys, + swgDeviceSettings, + errorResponse + ); + + if (httpRC / 100 != 2) + { + qDebug("AFCWorker::updateDeviceFrequency: error %d: %s", httpRC, qPrintable(*errorResponse.getMessage())); + return false; + } + + return true; +} + +int AFCWorker::getDeviceDirection(DeviceAPI *deviceAPI) +{ + if (deviceAPI->getSampleSink()) { + return 1; + } else if (deviceAPI->getSampleMIMO()) { + return 2; + } + + return 0; +} + +void AFCWorker::getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey) +{ + const QString& deviceHwId = deviceAPI->getHardwareId(); + + if (deviceAPI->getSampleSink()) + { + if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(deviceHwId)) { + settingsKey = WebAPIUtils::m_sinkDeviceHwIdToSettingsKey[deviceHwId]; + } + } + else if (deviceAPI->getSampleMIMO()) + { + if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(deviceHwId)) { + settingsKey = WebAPIUtils::m_mimoDeviceHwIdToSettingsKey[deviceHwId]; + } + } + else + { + if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(deviceHwId)) { + settingsKey = WebAPIUtils::m_sourceDeviceHwIdToSettingsKey[deviceHwId]; + } + } +} diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index bc074bfd4..744523bc0 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -19,6 +19,7 @@ #define INCLUDE_FEATURE_AFCWORKER_H_ #include <QObject> +#include <QMap> #include <QTimer> #include "util/message.h" @@ -27,6 +28,8 @@ #include "afcsettings.h" class WebAPIAdapterInterface; +class DeviceSet; +class ChannelAPI; class AFCWorker : public QObject { @@ -55,22 +58,23 @@ public: { } }; - class MsgPTT : public Message { + class MsgTrackedDeviceChange : public Message { MESSAGE_CLASS_DECLARATION public: - bool getTx() const { return m_tx; } + int getDeviceIndex() const { return m_deviceIndex; } - static MsgPTT* create(bool tx) { - return new MsgPTT(tx); + static MsgTrackedDeviceChange* create(int deviceIndex) + { + return new MsgTrackedDeviceChange(deviceIndex); } private: - bool m_tx; + int m_deviceIndex; - MsgPTT(bool tx) : + MsgTrackedDeviceChange(int deviceIndex) : Message(), - m_tx(tx) + m_deviceIndex(deviceIndex) { } }; @@ -84,17 +88,59 @@ public: void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; } private: + struct ChannelTracking + { + int m_channelOffset; + int m_trackerOffset; + int m_channelDirection; + + ChannelTracking() : + m_channelOffset(0), + m_trackerOffset(0), + m_channelDirection(0) + {} + + ChannelTracking(int channelOffset, int trackerOffset, int channelDirection) : + m_channelOffset(channelOffset), + m_trackerOffset(trackerOffset), + m_channelDirection(m_channelDirection) + {} + + ChannelTracking(const ChannelTracking& other) : + m_channelOffset(other.m_channelOffset), + m_trackerOffset(other.m_trackerOffset), + m_channelDirection(other.m_channelDirection) + {} + }; + WebAPIAdapterInterface *m_webAPIAdapterInterface; MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication MessageQueue *m_msgQueueToGUI; //!< Queue to report state to GUI AFCSettings m_settings; bool m_running; - bool m_tx; + DeviceSet *m_trackerDeviceSet; + DeviceSet *m_trackedDeviceSet; + ChannelAPI *m_freqTracker; + uint64_t m_trackerDeviceFrequency; + int m_trackerChannelOffset; + QMap<ChannelAPI*, ChannelTracking> m_channelsMap; QTimer m_updateTimer; QMutex m_mutex; bool handleMessage(const Message& cmd); void applySettings(const AFCSettings& settings, bool force = false); + void initTrackerDeviceSet(int deviceSetIndex); + void initTrackedDeviceSet(int deviceSetIndex); + void processChannelSettings( + const ChannelAPI *channelAPI, + const QList<QString> &channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings + ); + void updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset); + void updateTarget(); + bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); + int getDeviceDirection(DeviceAPI *deviceAPI); + void getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey); private slots: void handleInputMessages(); diff --git a/sdrbase/channel/channelapi.cpp b/sdrbase/channel/channelapi.cpp index fa8ecb183..54cddb6b9 100644 --- a/sdrbase/channel/channelapi.cpp +++ b/sdrbase/channel/channelapi.cpp @@ -27,4 +27,15 @@ ChannelAPI::ChannelAPI(const QString& name, StreamType streamType) : m_deviceSetIndex(0), m_deviceAPI(0), m_uid(UidCalculator::getNewObjectId()) -{ } \ No newline at end of file +{ } + +void ChannelAPI::addFeatureSettingsFeedback(Feature *feature) +{ + m_featuresSettingsFeedback.removeOne(feature); + m_featuresSettingsFeedback.append(feature); +} + +void ChannelAPI::removeFeatureSettingsFeedback(Feature *feature) +{ + m_featuresSettingsFeedback.removeOne(feature); +} diff --git a/sdrbase/channel/channelapi.h b/sdrbase/channel/channelapi.h index f1b5479fc..f0bde4a02 100644 --- a/sdrbase/channel/channelapi.h +++ b/sdrbase/channel/channelapi.h @@ -22,11 +22,14 @@ #include <QString> #include <QByteArray> +#include <QList> + #include <stdint.h> #include "export.h" class DeviceAPI; +class Feature; namespace SWGSDRangel { @@ -116,12 +119,18 @@ public: void setDeviceAPI(DeviceAPI *deviceAPI) { m_deviceAPI = deviceAPI; } uint64_t getUID() const { return m_uid; } + // Features support + void addFeatureSettingsFeedback(Feature *feature); + void removeFeatureSettingsFeedback(Feature *feature); + // MIMO support StreamType getStreamType() const { return m_streamType; } virtual int getNbSinkStreams() const = 0; virtual int getNbSourceStreams() const = 0; virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const = 0; +protected: + QList<Feature*> m_featuresSettingsFeedback; //!< list of features to report back settings changes in swagger API format private: StreamType m_streamType; diff --git a/sdrbase/feature/feature.cpp b/sdrbase/feature/feature.cpp index 75ce9f970..2af1a49c1 100644 --- a/sdrbase/feature/feature.cpp +++ b/sdrbase/feature/feature.cpp @@ -24,6 +24,8 @@ #include "feature.h" +MESSAGE_CLASS_DEFINITION(Feature::MsgChannelSettings, Message) + Feature::Feature(const QString& name, WebAPIAdapterInterface *webAPIAdapterInterface) : m_name(name), m_uid(UidCalculator::getNewObjectId()), diff --git a/sdrbase/feature/feature.h b/sdrbase/feature/feature.h index f41b79e21..06e8a08f2 100644 --- a/sdrbase/feature/feature.h +++ b/sdrbase/feature/feature.h @@ -29,6 +29,7 @@ #include "util/messagequeue.h" class WebAPIAdapterInterface; +class ChannelAPI; namespace SWGSDRangel { @@ -36,11 +37,50 @@ namespace SWGSDRangel class SWGFeatureReport; class SWGFeatureActions; class SWGDeviceState; + class SWGChannelSettings; } class SDRBASE_API Feature : public QObject { Q_OBJECT public: + class MsgChannelSettings : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const ChannelAPI *getChannelAPI() const { return m_channelAPI; } + const QList<QString>& getChannelSettingsKeys() const { return m_channelSettingsKeys; } + SWGSDRangel::SWGChannelSettings *getSWGSettings() const { return m_swgSettings; } + bool getForce() const { return m_force; } + + static MsgChannelSettings* create( + const ChannelAPI *channelAPI, + const QList<QString>& channelSettingsKey, + SWGSDRangel::SWGChannelSettings *swgSettings, + bool force) + { + return new MsgChannelSettings(channelAPI, channelSettingsKey, swgSettings, force); + } + + private: + const ChannelAPI *m_channelAPI; + QList<QString> m_channelSettingsKeys; + SWGSDRangel::SWGChannelSettings *m_swgSettings; + bool m_force; + + MsgChannelSettings( + const ChannelAPI *channelAPI, + const QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgSettings, + bool force + ) : + Message(), + m_channelAPI(channelAPI), + m_channelSettingsKeys(channelSettingsKeys), + m_swgSettings(swgSettings), + m_force(force) + { } + }; + enum FeatureState { StNotStarted, //!< feature is before initialization StIdle, //!< feature is idle diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 376da9135..f17fd8983 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -25,6 +25,7 @@ #include "httpdocrootsettings.h" #include "webapirequestmapper.h" +#include "webapiutils.h" #include "SWGInstanceSummaryResponse.h" #include "SWGInstanceConfigResponse.h" #include "SWGInstanceDevicesResponse.h" @@ -56,205 +57,6 @@ #include "SWGFeatureReport.h" #include "SWGFeatureActions.h" -const QMap<QString, QString> WebAPIRequestMapper::m_channelURIToSettingsKey = { - {"sdrangel.channel.amdemod", "AMDemodSettings"}, - {"de.maintech.sdrangelove.channel.am", "AMDemodSettings"}, // remap - {"sdrangel.channeltx.modam", "AMModSettings"}, - {"sdrangel.channeltx.modatv", "ATVModSettings"}, - {"sdrangel.channel.bfm", "BFMDemodSettings"}, - {"sdrangel.channel.chanalyzer", "ChannelAnalyzerSettings"}, - {"sdrangel.channel.chanalyzerng", "ChannelAnalyzerSettings"}, // remap - {"org.f4exb.sdrangelove.channel.chanalyzer", "ChannelAnalyzerSettings"}, // remap - {"sdrangel.channel.demodatv", "ATVDemodSettings"}, - {"sdrangel.channel.demoddatv", "DATVDemodSettings"}, - {"sdrangel.channel.dsddemod", "DSDDemodSettings"}, - {"sdrangel.channel.filesink", "FileSinkSettings"}, - {"sdrangel.channeltx.filesource", "FileSourceSettings"}, - {"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"}, - {"sdrangel.channeltx.freedvmod", "FreeDVModSettings"}, - {"sdrangel.channel.freqtracker", "FreqTrackerSettings"}, - {"sdrangel.channel.nfmdemod", "NFMDemodSettings"}, - {"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap - {"sdrangel.channeltx.modnfm", "NFMModSettings"}, - {"sdrangel.demod.localsink", "LocalSinkSettings"}, - {"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap - {"sdrangel.channel.localsource", "LocalSourceSettings"}, - {"sdrangel.channeltx.modpacket", "PacketModSettings"}, - {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, - {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, - {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, - {"sdrangel.channeltx.modssb", "SSBModSettings"}, - {"sdrangel.channel.ssbdemod", "SSBDemodSettings"}, - {"de.maintech.sdrangelove.channel.ssb", "SSBDemodSettings"}, // remap - {"sdrangel.channeltx.udpsource", "UDPSourceSettings"}, - {"sdrangel.channeltx.udpsink", "UDPSourceSettings"}, // remap - {"sdrangel.channel.udpsink", "UDPSinkSettings"}, - {"sdrangel.channel.udpsrc", "UDPSinkSettings"}, // remap - {"sdrangel.channel.wfmdemod", "WFMDemodSettings"}, - {"de.maintech.sdrangelove.channel.wfm", "WFMDemodSettings"}, // remap - {"sdrangel.channeltx.modwfm", "WFMModSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_deviceIdToSettingsKey = { - {"sdrangel.samplesource.airspy", "airspySettings"}, - {"sdrangel.samplesource.airspyhf", "airspyHFSettings"}, - {"sdrangel.samplesource.bladerf1input", "bladeRF1InputSettings"}, - {"sdrangel.samplesource.bladerf", "bladeRF1InputSettings"}, // remap - {"sdrangel.samplesink.bladerf1output", "bladeRF1OutputSettings"}, - {"sdrangel.samplesource.bladerf1output", "bladeRF1OutputSettings"}, // remap - {"sdrangel.samplesource.bladerfoutput", "bladeRF1OutputSettings"}, // remap - {"sdrangel.samplesource.bladerf2input", "bladeRF2InputSettings"}, - {"sdrangel.samplesink.bladerf2output", "bladeRF2OutputSettings"}, - {"sdrangel.samplesource.bladerf2output", "bladeRF2OutputSettings"}, // remap - {"sdrangel.samplesource.fcdpro", "fcdProSettings"}, - {"sdrangel.samplesource.fcdproplus", "fcdProPlusSettings"}, - {"sdrangel.samplesource.fileinput", "fileInputSettings"}, - {"sdrangel.samplesource.filesource", "fileInputSettings"}, // remap - {"sdrangel.samplesource.hackrf", "hackRFInputSettings"}, - {"sdrangel.samplesink.hackrf", "hackRFOutputSettings"}, - {"sdrangel.samplesource.hackrfoutput", "hackRFOutputSettings"}, // remap - {"sdrangel.samplesource.kiwisdrsource", "kiwiSDRSettings"}, - {"sdrangel.samplesource.limesdr", "limeSdrInputSettings"}, - {"sdrangel.samplesink.limesdr", "limeSdrOutputSettings"}, - {"sdrangel.samplesource.localinput", "localInputSettings"}, - {"sdrangel.samplesink.localoutput", "localOutputSettings"}, - {"sdrangel.samplesource.localoutput", "localOutputSettings"}, // remap - {"sdrangel.samplesource.perseus", "perseusSettings"}, - {"sdrangel.samplesource.plutosdr", "plutoSdrInputSettings"}, - {"sdrangel.samplesink.plutosdr", "plutoSdrOutputSettings"}, - {"sdrangel.samplesource.rtlsdr", "rtlSdrSettings"}, - {"sdrangel.samplesource.remoteinput", "remoteInputSettings"}, - {"sdrangel.samplesink.remoteoutput", "remoteOutputSettings"}, - {"sdrangel.samplesource.sdrplay", "sdrPlaySettings"}, - {"sdrangel.samplesource.soapysdrinput", "soapySDRInputSettings"}, - {"sdrangel.samplesink.soapysdroutput", "soapySDROutputSettings"}, - {"sdrangel.samplesource.testsource", "testSourceSettings"}, - {"sdrangel.samplesource.usrp", "usrpInputSettings"}, - {"sdrangel.samplesink.usrp", "usrpOutputSettings"}, - {"sdrangel.samplesource.xtrx", "XtrxInputSettings"}, - {"sdrangel.samplesink.xtrx", "XtrxOutputSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToSettingsKey = { - {"AMDemod", "AMDemodSettings"}, - {"AMMod", "AMModSettings"}, - {"ATVDemod", "ATVDemodSettings"}, - {"ATVMod", "ATVModSettings"}, - {"BFMDemod", "BFMDemodSettings"}, - {"ChannelAnalyzer", "ChannelAnalyzerSettings"}, - {"DATVDemod", "DATVDemodSettings"}, - {"DSDDemod", "DSDDemodSettings"}, - {"FileSink", "FileSinkSettings"}, - {"FileSource", "FileSourceSettings"}, - {"FreeDVDemod", "FreeDVDemodSettings"}, - {"FreeDVMod", "FreeDVModSettings"}, - {"FreqTracker", "FreqTrackerSettings"}, - {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"}, - {"NFMDemod", "NFMDemodSettings"}, - {"NFMMod", "NFMModSettings"}, - {"PacketMod", "PacketModSettings"}, - {"LocalSink", "LocalSinkSettings"}, - {"LocalSource", "LocalSourceSettings"}, - {"RemoteSink", "RemoteSinkSettings"}, - {"RemoteSource", "RemoteSourceSettings"}, - {"SSBMod", "SSBModSettings"}, - {"SSBDemod", "SSBDemodSettings"}, - {"UDPSink", "UDPSourceSettings"}, - {"UDPSource", "UDPSinkSettings"}, - {"WFMDemod", "WFMDemodSettings"}, - {"WFMMod", "WFMModSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToActionsKey = { - {"FileSink", "FileSinkActions"}, - {"FileSource", "FileSourceActions"}, - {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModActions"}, - {"PacketMod", "PacketModActions"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_sourceDeviceHwIdToSettingsKey = { - {"Airspy", "airspySettings"}, - {"AirspyHF", "airspyHFSettings"}, - {"BladeRF1", "bladeRF1InputSettings"}, - {"BladeRF2", "bladeRF2InputSettings"}, - {"FCDPro", "fcdProSettings"}, - {"FCDPro+", "fcdProPlusSettings"}, - {"FileInput", "fileInputSettings"}, - {"HackRF", "hackRFInputSettings"}, - {"KiwiSDR", "kiwiSDRSettings"}, - {"LimeSDR", "limeSdrInputSettings"}, - {"LocalInput", "localInputSettings"}, - {"Perseus", "perseusSettings"}, - {"PlutoSDR", "plutoSdrInputSettings"}, - {"RTLSDR", "rtlSdrSettings"}, - {"RemoteInput", "remoteInputSettings"}, - {"SDRplay1", "sdrPlaySettings"}, - {"SoapySDR", "soapySDRInputSettings"}, - {"TestSource", "testSourceSettings"}, - {"USRP", "usrpInputSettings"}, - {"XTRX", "XtrxInputSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_sourceDeviceHwIdToActionsKey = { - {"Airspy", "airspyActions"}, - {"AirspyHF", "airspyHFActions"}, - {"BladeRF1", "bladeRF1InputActions"}, - {"FCDPro", "fcdProActions"}, - {"FCDPro+", "fcdProPlusActions"}, - {"HackRF", "hackRFInputActions"}, - {"KiwiSDR", "kiwiSDRActions"}, - {"LimeSDR", "limeSdrInputActions"}, - {"LocalInput", "localInputActions"}, - {"Perseus", "perseusActions"}, - {"PlutoSDR", "plutoSdrInputActions"}, - {"RemoteInput", "remoteInputActions"}, - {"RTLSDR", "rtlSdrActions"}, - {"SDRplay1", "sdrPlayActions"}, - {"SoapySDR", "soapySDRInputActions"}, - {"TestSource", "testSourceActions"}, - {"USRP", "usrpSourceActions"}, - {"XTRX", "xtrxInputActions"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_sinkDeviceHwIdToSettingsKey = { - {"BladeRF1", "bladeRF1OutputSettings"}, - {"BladeRF2", "bladeRF2OutputSettings"}, - {"HackRF", "hackRFOutputSettings"}, - {"LimeSDR", "limeSdrOutputSettings"}, - {"LocalOutput", "localOutputSettings"}, - {"PlutoSDR", "plutoSdrOutputSettings"}, - {"RemoteOutput", "remoteOutputSettings"}, - {"SoapySDR", "soapySDROutputSettings"}, - {"USRP", "usrpOutputSettings"}, - {"XTRX", "xtrxOutputSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_sinkDeviceHwIdToActionsKey = { -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToSettingsKey= { - {"BladeRF2", "bladeRF2MIMOSettings"}, - {"TestMI", "testMISettings"}, - {"TestMOSync", "testMOSyncSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToActionsKey= { -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_featureTypeToSettingsKey = { - {"SimplePTT", "SimplePTTSettings"}, - {"RigCtlServer", "RigCtlServerSettings"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_featureTypeToActionsKey = { - {"SimplePTT", "SimplePTTActions"} -}; - -const QMap<QString, QString> WebAPIRequestMapper::m_featureURIToSettingsKey = { - {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, - {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"} -}; - WebAPIRequestMapper::WebAPIRequestMapper(QObject* parent) : HttpRequestHandler(parent), m_adapter(0) @@ -3025,16 +2827,24 @@ bool WebAPIRequestMapper::validateDeviceSettings( if (deviceSettings.getDirection() == 0) // source { - if (m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { - deviceSettingsKey = m_sourceDeviceHwIdToSettingsKey[*deviceHwType]; + if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceSettingsKey = WebAPIUtils::m_sourceDeviceHwIdToSettingsKey[*deviceHwType]; } else { return false; } } else if (deviceSettings.getDirection() == 1) // sink { - if (m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { - deviceSettingsKey = m_sinkDeviceHwIdToSettingsKey[*deviceHwType]; + if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceSettingsKey = WebAPIUtils::m_sinkDeviceHwIdToSettingsKey[*deviceHwType]; + } else { + return false; + } + } + else if (deviceSettings.getDirection() == 2) // MIMO + { + if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceSettingsKey = WebAPIUtils::m_mimoDeviceHwIdToSettingsKey[*deviceHwType]; } else { return false; } @@ -3069,24 +2879,24 @@ bool WebAPIRequestMapper::validateDeviceActions( if (deviceActions.getDirection() == 0) // source { - if (m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { - deviceActionsKey = m_sourceDeviceHwIdToActionsKey[*deviceHwType]; + if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceActionsKey = WebAPIUtils::m_sourceDeviceHwIdToActionsKey[*deviceHwType]; } else { return false; } } else if (deviceActions.getDirection() == 1) // sink { - if (m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { - deviceActionsKey = m_sinkDeviceHwIdToActionsKey[*deviceHwType]; + if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceActionsKey = WebAPIUtils::m_sinkDeviceHwIdToActionsKey[*deviceHwType]; } else { return false; } } else if (deviceActions.getDirection() == 2) // MIMO { - if (m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { - deviceActionsKey = m_mimoDeviceHwIdToActionsKey[*deviceHwType]; + if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { + deviceActionsKey = WebAPIUtils::m_mimoDeviceHwIdToActionsKey[*deviceHwType]; } else { return false; } @@ -3118,8 +2928,8 @@ bool WebAPIRequestMapper::validateChannelSettings( QString *channelType = channelSettings.getChannelType(); - if (m_channelTypeToSettingsKey.contains(*channelType)) { - return getChannelSettings(m_channelTypeToSettingsKey[*channelType], &channelSettings, jsonObject, channelSettingsKeys); + if (WebAPIUtils::m_channelTypeToSettingsKey.contains(*channelType)) { + return getChannelSettings(WebAPIUtils::m_channelTypeToSettingsKey[*channelType], &channelSettings, jsonObject, channelSettingsKeys); } else { return false; } @@ -3144,8 +2954,8 @@ bool WebAPIRequestMapper::validateChannelActions( QString *channelType = channelActions.getChannelType(); - if (m_channelTypeToActionsKey.contains(*channelType)) { - return getChannelActions(m_channelTypeToActionsKey[*channelType], &channelActions, jsonObject, channelActionsKeys); + if (WebAPIUtils::m_channelTypeToActionsKey.contains(*channelType)) { + return getChannelActions(WebAPIUtils::m_channelTypeToActionsKey[*channelType], &channelActions, jsonObject, channelActionsKeys); } else { return false; } @@ -3164,8 +2974,8 @@ bool WebAPIRequestMapper::validateFeatureSettings( QString *featureType = featureSettings.getFeatureType(); - if (m_featureTypeToSettingsKey.contains(*featureType)) { - return getFeatureSettings(m_featureTypeToSettingsKey[*featureType], &featureSettings, jsonObject, featureSettingsKeys); + if (WebAPIUtils::m_featureTypeToSettingsKey.contains(*featureType)) { + return getFeatureSettings(WebAPIUtils::m_featureTypeToSettingsKey[*featureType], &featureSettings, jsonObject, featureSettingsKeys); } else { return false; } @@ -3184,8 +2994,8 @@ bool WebAPIRequestMapper::validateFeatureActions( QString *featureType = featureActions.getFeatureType(); - if (m_featureTypeToActionsKey.contains(*featureType)) { - return getFeatureActions(m_featureTypeToActionsKey[*featureType], &featureActions, jsonObject, featureActionsKeys); + if (WebAPIUtils::m_featureTypeToActionsKey.contains(*featureType)) { + return getFeatureActions(WebAPIUtils::m_featureTypeToActionsKey[*featureType], &featureActions, jsonObject, featureActionsKeys); } else { return false; } @@ -3643,12 +3453,12 @@ bool WebAPIRequestMapper::appendPresetFeatureKeys( feature->setFeatureIdUri(featureURI); featureKeys.m_keys.append("featureIdURI"); - if (featureSettingsJson.contains("config") && m_featureURIToSettingsKey.contains(*featureURI)) + if (featureSettingsJson.contains("config") && WebAPIUtils::m_featureURIToSettingsKey.contains(*featureURI)) { SWGSDRangel::SWGFeatureSettings *featureSettings = new SWGSDRangel::SWGFeatureSettings(); feature->setConfig(featureSettings); return getFeatureSettings( - m_channelURIToSettingsKey[*featureURI], + WebAPIUtils::m_channelURIToSettingsKey[*featureURI], featureSettings, featureSettingsJson["config"].toObject(), featureKeys.m_featureKeys @@ -3677,11 +3487,11 @@ bool WebAPIRequestMapper::appendPresetChannelKeys( channel->setChannelIdUri(channelURI); channelKeys.m_keys.append("channelIdURI"); - if (channelSettingsJson.contains("config") && m_channelURIToSettingsKey.contains(*channelURI)) + if (channelSettingsJson.contains("config") && WebAPIUtils::m_channelURIToSettingsKey.contains(*channelURI)) { SWGSDRangel::SWGChannelSettings *channelSettings = new SWGSDRangel::SWGChannelSettings(); channel->setConfig(channelSettings); - return getChannelSettings(m_channelURIToSettingsKey[*channelURI], channelSettings, channelSettingsJson["config"].toObject(), channelKeys.m_channelKeys); + return getChannelSettings(WebAPIUtils::m_channelURIToSettingsKey[*channelURI], channelSettings, channelSettingsJson["config"].toObject(), channelKeys.m_channelKeys); } else { @@ -3933,11 +3743,11 @@ bool WebAPIRequestMapper::appendPresetDeviceKeys( devicelKeys.m_keys.append("deviceSequence"); } - if (deviceSettngsJson.contains("config") && m_deviceIdToSettingsKey.contains(*deviceId)) + if (deviceSettngsJson.contains("config") && WebAPIUtils::m_deviceIdToSettingsKey.contains(*deviceId)) { SWGSDRangel::SWGDeviceSettings *deviceSettings = new SWGSDRangel::SWGDeviceSettings(); device->setConfig(deviceSettings); - return getDeviceSettings(m_deviceIdToSettingsKey[*deviceId], deviceSettings, deviceSettngsJson["config"].toObject(), devicelKeys.m_deviceKeys); + return getDeviceSettings(WebAPIUtils::m_deviceIdToSettingsKey[*deviceId], deviceSettings, deviceSettngsJson["config"].toObject(), devicelKeys.m_deviceKeys); } else { diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index 86df2e98d..f392c639f 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -21,6 +21,224 @@ #include "webapiutils.h" +const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = { + {"sdrangel.channel.amdemod", "AMDemodSettings"}, + {"de.maintech.sdrangelove.channel.am", "AMDemodSettings"}, // remap + {"sdrangel.channeltx.modam", "AMModSettings"}, + {"sdrangel.channeltx.modatv", "ATVModSettings"}, + {"sdrangel.channel.bfm", "BFMDemodSettings"}, + {"sdrangel.channel.chanalyzer", "ChannelAnalyzerSettings"}, + {"sdrangel.channel.chanalyzerng", "ChannelAnalyzerSettings"}, // remap + {"org.f4exb.sdrangelove.channel.chanalyzer", "ChannelAnalyzerSettings"}, // remap + {"sdrangel.channel.chirpchatdemod", "ChirpChatDemodSettings"}, + {"sdrangel.channel.modchirpchat", "ChirpChatModSettings"}, + {"sdrangel.channel.demodatv", "ATVDemodSettings"}, + {"sdrangel.channel.demoddatv", "DATVDemodSettings"}, + {"sdrangel.channel.dsddemod", "DSDDemodSettings"}, + {"sdrangel.channel.filesink", "FileSinkSettings"}, + {"sdrangel.channeltx.filesource", "FileSourceSettings"}, + {"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"}, + {"sdrangel.channeltx.freedvmod", "FreeDVModSettings"}, + {"sdrangel.channel.freqtracker", "FreqTrackerSettings"}, + {"sdrangel.channel.nfmdemod", "NFMDemodSettings"}, + {"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap + {"sdrangel.channeltx.modnfm", "NFMModSettings"}, + {"sdrangel.demod.localsink", "LocalSinkSettings"}, + {"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap + {"sdrangel.channel.localsource", "LocalSourceSettings"}, + {"sdrangel.channeltx.modpacket", "PacketModSettings"}, + {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, + {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, + {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, + {"sdrangel.channeltx.modssb", "SSBModSettings"}, + {"sdrangel.channel.ssbdemod", "SSBDemodSettings"}, + {"de.maintech.sdrangelove.channel.ssb", "SSBDemodSettings"}, // remap + {"sdrangel.channeltx.udpsource", "UDPSourceSettings"}, + {"sdrangel.channeltx.udpsink", "UDPSourceSettings"}, // remap + {"sdrangel.channel.udpsink", "UDPSinkSettings"}, + {"sdrangel.channel.udpsrc", "UDPSinkSettings"}, // remap + {"sdrangel.channel.wfmdemod", "WFMDemodSettings"}, + {"de.maintech.sdrangelove.channel.wfm", "WFMDemodSettings"}, // remap + {"sdrangel.channeltx.modwfm", "WFMModSettings"}, + {"sdrangel.channel.beamsteeringcwmod", "BeamSteeringCWModSettings"}, + {"sdrangel.channelmimo.interferometer", "InterferometerSettings"}, + {"sdrangel.channel.sigmffilesink", "SigMFFileSinkSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_deviceIdToSettingsKey = { + {"sdrangel.samplesource.airspy", "airspySettings"}, + {"sdrangel.samplesource.airspyhf", "airspyHFSettings"}, + {"sdrangel.samplesource.bladerf1input", "bladeRF1InputSettings"}, + {"sdrangel.samplesource.bladerf", "bladeRF1InputSettings"}, // remap + {"sdrangel.samplesink.bladerf1output", "bladeRF1OutputSettings"}, + {"sdrangel.samplesource.bladerf1output", "bladeRF1OutputSettings"}, // remap + {"sdrangel.samplesource.bladerfoutput", "bladeRF1OutputSettings"}, // remap + {"sdrangel.samplesource.bladerf2input", "bladeRF2InputSettings"}, + {"sdrangel.samplesink.bladerf2output", "bladeRF2OutputSettings"}, + {"sdrangel.samplesource.bladerf2output", "bladeRF2OutputSettings"}, // remap + {"sdrangel.samplemimo.bladerf2mimo", "bladeRF2MIMOSettings"}, + {"sdrangel.samplesource.fcdpro", "fcdProSettings"}, + {"sdrangel.samplesource.fcdproplus", "fcdProPlusSettings"}, + {"sdrangel.samplesource.fileinput", "fileInputSettings"}, + {"sdrangel.samplesource.filesource", "fileInputSettings"}, // remap + {"sdrangel.samplesource.hackrf", "hackRFInputSettings"}, + {"sdrangel.samplesink.hackrf", "hackRFOutputSettings"}, + {"sdrangel.samplesource.hackrfoutput", "hackRFOutputSettings"}, // remap + {"sdrangel.samplesource.kiwisdrsource", "kiwiSDRSettings"}, + {"sdrangel.samplesource.limesdr", "limeSdrInputSettings"}, + {"sdrangel.samplesink.limesdr", "limeSdrOutputSettings"}, + {"sdrangel.samplesource.localinput", "localInputSettings"}, + {"sdrangel.samplesink.localoutput", "localOutputSettings"}, + {"sdrangel.samplesource.localoutput", "localOutputSettings"}, // remap + {"sdrangel.samplemimo.metismiso", "metisMISOSettings"}, + {"sdrangel.samplesource.perseus", "perseusSettings"}, + {"sdrangel.samplesource.plutosdr", "plutoSdrInputSettings"}, + {"sdrangel.samplesink.plutosdr", "plutoSdrOutputSettings"}, + {"sdrangel.samplesource.rtlsdr", "rtlSdrSettings"}, + {"sdrangel.samplesource.remoteinput", "remoteInputSettings"}, + {"sdrangel.samplesink.remoteoutput", "remoteOutputSettings"}, + {"sdrangel.samplesource.sdrplay", "sdrPlaySettings"}, + {"sdrangel.samplesource.sigmffileinput", "sigMFFileInputSettings"}, + {"sdrangel.samplesource.soapysdrinput", "soapySDRInputSettings"}, + {"sdrangel.samplesink.soapysdroutput", "soapySDROutputSettings"}, + {"sdrangel.samplesource.testsource", "testSourceSettings"}, + {"sdrangel.samplemimo.testmi", "testMISettings"}, + {"sdrangel.samplemimo.testmosync", "testMOSyncSettings"}, + {"sdrangel.samplesource.usrp", "usrpInputSettings"}, + {"sdrangel.samplesink.usrp", "usrpOutputSettings"}, + {"sdrangel.samplesource.xtrx", "xtrxInputSettings"}, + {"sdrangel.samplesink.xtrx", "xtrxOutputSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = { + {"AMDemod", "AMDemodSettings"}, + {"AMMod", "AMModSettings"}, + {"ATVDemod", "ATVDemodSettings"}, + {"ATVMod", "ATVModSettings"}, + {"BFMDemod", "BFMDemodSettings"}, + {"ChannelAnalyzer", "ChannelAnalyzerSettings"}, + {"ChirpChatDemod", "ChirpChatDemodSettings"}, + {"ChirpChatMod", "ChirpChatModSettings"}, + {"DATVDemod", "DATVDemodSettings"}, + {"DSDDemod", "DSDDemodSettings"}, + {"FileSink", "FileSinkSettings"}, + {"FileSource", "FileSourceSettings"}, + {"FreeDVDemod", "FreeDVDemodSettings"}, + {"FreeDVMod", "FreeDVModSettings"}, + {"FreqTracker", "FreqTrackerSettings"}, + {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"}, + {"NFMDemod", "NFMDemodSettings"}, + {"NFMMod", "NFMModSettings"}, + {"PacketMod", "PacketModSettings"}, + {"LocalSink", "LocalSinkSettings"}, + {"LocalSource", "LocalSourceSettings"}, + {"RemoteSink", "RemoteSinkSettings"}, + {"RemoteSource", "RemoteSourceSettings"}, + {"SSBMod", "SSBModSettings"}, + {"SSBDemod", "SSBDemodSettings"}, + {"UDPSink", "UDPSourceSettings"}, + {"UDPSource", "UDPSinkSettings"}, + {"WFMDemod", "WFMDemodSettings"}, + {"WFMMod", "WFMModSettings"}, + {"BeamSteeringCWMod", "BeamSteeringCWModSettings"}, + {"Interferometer", "InterferometerSettings"}, + {"SigMFFileSink", "SigMFFileSinkSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_channelTypeToActionsKey = { + {"FileSink", "FileSinkActions"}, + {"FileSource", "FileSourceActions"}, + {"SigMFFileSink", "SigMFFileSinkActions"}, + {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModActions"}, + {"PacketMod", "PacketModActions"} +}; + +const QMap<QString, QString> WebAPIUtils::m_sourceDeviceHwIdToSettingsKey = { + {"Airspy", "airspySettings"}, + {"AirspyHF", "airspyHFSettings"}, + {"BladeRF1", "bladeRF1InputSettings"}, + {"BladeRF2", "bladeRF2InputSettings"}, + {"FCDPro", "fcdProSettings"}, + {"FCDPro+", "fcdProPlusSettings"}, + {"FileInput", "fileInputSettings"}, + {"HackRF", "hackRFInputSettings"}, + {"KiwiSDR", "kiwiSDRSettings"}, + {"LimeSDR", "limeSdrInputSettings"}, + {"LocalInput", "localInputSettings"}, + {"Perseus", "perseusSettings"}, + {"PlutoSDR", "plutoSdrInputSettings"}, + {"RTLSDR", "rtlSdrSettings"}, + {"RemoteInput", "remoteInputSettings"}, + {"SDRplay1", "sdrPlaySettings"}, + {"SigMFFileInput", "sigMFFileInputSettings"}, + {"SoapySDR", "soapySDRInputSettings"}, + {"TestSource", "testSourceSettings"}, + {"USRP", "usrpInputSettings"}, + {"XTRX", "xtrxInputSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_sourceDeviceHwIdToActionsKey = { + {"Airspy", "airspyActions"}, + {"AirspyHF", "airspyHFActions"}, + {"BladeRF1", "bladeRF1InputActions"}, + {"FCDPro", "fcdProActions"}, + {"FCDPro+", "fcdProPlusActions"}, + {"HackRF", "hackRFInputActions"}, + {"KiwiSDR", "kiwiSDRActions"}, + {"LimeSDR", "limeSdrInputActions"}, + {"LocalInput", "localInputActions"}, + {"Perseus", "perseusActions"}, + {"PlutoSDR", "plutoSdrInputActions"}, + {"RemoteInput", "remoteInputActions"}, + {"RTLSDR", "rtlSdrActions"}, + {"SDRplay1", "sdrPlayActions"}, + {"SigMFFileInput", "sigMFFileActions"}, + {"SoapySDR", "soapySDRInputActions"}, + {"TestSource", "testSourceActions"}, + {"USRP", "usrpSourceActions"}, + {"XTRX", "xtrxInputActions"} +}; + +const QMap<QString, QString> WebAPIUtils::m_sinkDeviceHwIdToSettingsKey = { + {"BladeRF1", "bladeRF1OutputSettings"}, + {"BladeRF2", "bladeRF2OutputSettings"}, + {"HackRF", "hackRFOutputSettings"}, + {"LimeSDR", "limeSdrOutputSettings"}, + {"LocalOutput", "localOutputSettings"}, + {"PlutoSDR", "plutoSdrOutputSettings"}, + {"RemoteOutput", "remoteOutputSettings"}, + {"SoapySDR", "soapySDROutputSettings"}, + {"USRP", "usrpOutputSettings"}, + {"XTRX", "xtrxOutputSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_sinkDeviceHwIdToActionsKey = { +}; + +const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToSettingsKey = { + {"BladeRF2", "bladeRF2MIMOSettings"}, + {"MetisMISO", "metisMISOSettings"}, + {"TestMI", "testMISettings"}, + {"TestMOSync", "testMOSyncSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToActionsKey = { +}; + +const QMap<QString, QString> WebAPIUtils::m_featureTypeToSettingsKey = { + {"SimplePTT", "SimplePTTSettings"}, + {"RigCtlServer", "RigCtlServerSettings"} +}; + +const QMap<QString, QString> WebAPIUtils::m_featureTypeToActionsKey = { + {"SimplePTT", "SimplePTTActions"} +}; + +const QMap<QString, QString> WebAPIUtils::m_featureURIToSettingsKey = { + {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, + {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"} +}; + // Get integer value from within JSON object bool WebAPIUtils::getObjectInt(const QJsonObject &json, const QString &key, int &value) { @@ -114,3 +332,193 @@ bool WebAPIUtils::setSubObjectDouble(QJsonObject &json, const QString &key, doub return false; } + +// look for value in key=value +bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value) +{ + // final + if (json.contains(key)) + { + value = json[key]; + return true; + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (extractValue(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} + +// look for [...] in key=[...] +bool WebAPIUtils::extractArray(const QJsonObject &json, const QString &key, QJsonArray &value) +{ + // final + if (json.contains(key)) + { + if (json[key].isArray()) + { + value = json[key].toArray(); + return true; + } + else + { + return false; + } + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (extractArray(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} + +// look for {...} in key={...} +bool WebAPIUtils::extractObject(const QJsonObject &json, const QString &key, QJsonObject &value) +{ + // final + if (json.contains(key)) + { + if (json[key].isObject()) + { + value = json[key].toObject(); + return true; + } + else + { + return false; + } + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (extractObject(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} + +// set value in key=value +bool WebAPIUtils::setValue(const QJsonObject &json, const QString &key, const QJsonValue &value) +{ + // final + if (json.contains(key)) + { + json[key] = value; + return true; + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (setValue(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} + +// set [...] in key=[...] +bool WebAPIUtils::setArray(const QJsonObject &json, const QString &key, const QJsonArray &value) +{ + // final + if (json.contains(key)) + { + if (json[key].isArray()) + { + json[key] = value; + return true; + } + else + { + return false; + } + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (setArray(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} + +// set {...} in key={...} +bool WebAPIUtils::setObject(const QJsonObject &json, const QString &key, const QJsonObject &value) +{ + // final + if (json.contains(key)) + { + if (json[key].isObject()) + { + json[key] = value; + return true; + } + else + { + return false; + } + } + else + { + for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++) + { + QJsonValue jsonValue = it.value(); + + if (jsonValue.isObject()) + { + if (setObject(jsonValue.toObject(), key, value)) { + return true; + } + } + } + } + + return false; +} diff --git a/sdrbase/webapi/webapiutils.h b/sdrbase/webapi/webapiutils.h index 3a99167f9..32ae7591e 100644 --- a/sdrbase/webapi/webapiutils.h +++ b/sdrbase/webapi/webapiutils.h @@ -21,17 +21,38 @@ #include <QJsonObject> #include <QString> +#include <QMap> #include "export.h" class SDRBASE_API WebAPIUtils { public: + static const QMap<QString, QString> m_channelURIToSettingsKey; + static const QMap<QString, QString> m_deviceIdToSettingsKey; + static const QMap<QString, QString> m_channelTypeToSettingsKey; + static const QMap<QString, QString> m_sourceDeviceHwIdToSettingsKey; + static const QMap<QString, QString> m_sinkDeviceHwIdToSettingsKey; + static const QMap<QString, QString> m_mimoDeviceHwIdToSettingsKey; + static const QMap<QString, QString> m_channelTypeToActionsKey; + static const QMap<QString, QString> m_sourceDeviceHwIdToActionsKey; + static const QMap<QString, QString> m_sinkDeviceHwIdToActionsKey; + static const QMap<QString, QString> m_mimoDeviceHwIdToActionsKey; + static const QMap<QString, QString> m_featureTypeToSettingsKey; + static const QMap<QString, QString> m_featureTypeToActionsKey; + static const QMap<QString, QString> m_featureURIToSettingsKey; + static bool getObjectInt(const QJsonObject &json, const QString &key, int &value); static bool getObjectString(const QJsonObject &json, const QString &key, QString &value); static bool getObjectObjects(const QJsonObject &json, const QString &key, QList<QJsonObject> &objects); static bool getSubObjectDouble(const QJsonObject &json, const QString &key, double &value); static bool setSubObjectDouble(QJsonObject &json, const QString &key, double value); + static bool extractValue(const QJsonObject &json, const QString &key, QJsonValue &value); + static bool extractArray(const QJsonObject &json, const QString &key, QJsonArray &value); + static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value); + static bool setValue(const QJsonObject &json, const QString &key, const QJsonValue &value); + static bool setArray(const QJsonObject &json, const QString &key, const QJsonArray &value); + static bool setObject(const QJsonObject &json, const QString &key, const QJsonObject &value); }; #endif From 6f4f7910f185eb46b0cd05f1fc7687cceae89703 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Fri, 23 Oct 2020 00:11:18 +0200 Subject: [PATCH 07/27] Channel settings feature feedback: all plugins --- plugins/channelrx/demodam/amdemod.cpp | 82 ++++++--- plugins/channelrx/demodam/amdemod.h | 7 + plugins/channelrx/demodbfm/bfmdemod.cpp | 86 +++++++--- plugins/channelrx/demodbfm/bfmdemod.h | 7 + plugins/channelrx/demoddsd/dsddemod.cpp | 86 +++++++--- plugins/channelrx/demoddsd/dsddemod.h | 7 + plugins/channelrx/demodfreedv/freedvdemod.cpp | 88 +++++++--- plugins/channelrx/demodfreedv/freedvdemod.h | 7 + plugins/channelrx/demodnfm/nfmdemod.cpp | 82 ++++++--- plugins/channelrx/demodnfm/nfmdemod.h | 7 + plugins/channelrx/demodssb/ssbdemod.cpp | 86 +++++++--- plugins/channelrx/demodssb/ssbdemod.h | 7 + plugins/channelrx/demodwfm/wfmdemod.cpp | 86 +++++++--- plugins/channelrx/demodwfm/wfmdemod.h | 7 + plugins/channelrx/filesink/filesink.cpp | 86 +++++++--- plugins/channelrx/filesink/filesink.h | 7 + plugins/channelrx/freqtracker/freqtracker.cpp | 81 ++++++--- plugins/channelrx/freqtracker/freqtracker.h | 7 + plugins/channelrx/localsink/localsink.cpp | 86 +++++++--- plugins/channelrx/localsink/localsink.h | 7 + plugins/channelrx/remotesink/remotesink.cpp | 86 +++++++--- plugins/channelrx/remotesink/remotesink.h | 7 + plugins/channelrx/udpsink/udpsink.cpp | 88 +++++++--- plugins/channelrx/udpsink/udpsink.h | 7 + plugins/channeltx/filesource/filesource.cpp | 86 +++++++--- plugins/channeltx/filesource/filesource.h | 7 + plugins/channeltx/localsource/localsource.cpp | 84 +++++++--- plugins/channeltx/localsource/localsource.h | 7 + .../mod802.15.4/ieee_802_15_4_mod.cpp | 84 +++++++--- .../channeltx/mod802.15.4/ieee_802_15_4_mod.h | 7 + plugins/channeltx/modam/ammod.cpp | 150 +++++++++++------ plugins/channeltx/modam/ammod.h | 7 + plugins/channeltx/modatv/atvmod.cpp | 86 +++++++--- plugins/channeltx/modatv/atvmod.h | 7 + plugins/channeltx/modfreedv/freedvmod.cpp | 150 +++++++++++------ plugins/channeltx/modfreedv/freedvmod.h | 7 + plugins/channeltx/modnfm/nfmmod.cpp | 148 +++++++++++------ plugins/channeltx/modnfm/nfmmod.h | 7 + plugins/channeltx/modpacket/packetmod.cpp | 84 +++++++--- plugins/channeltx/modpacket/packetmod.h | 7 + plugins/channeltx/modssb/ssbmod.cpp | 150 +++++++++++------ plugins/channeltx/modssb/ssbmod.h | 7 + plugins/channeltx/modwfm/wfmmod.cpp | 156 +++++++++++------- plugins/channeltx/modwfm/wfmmod.h | 7 + .../channeltx/remotesource/remotesource.cpp | 87 +++++++--- plugins/channeltx/remotesource/remotesource.h | 7 + plugins/channeltx/udpsource/udpsource.cpp | 86 +++++++--- plugins/channeltx/udpsource/udpsource.h | 7 + 48 files changed, 1881 insertions(+), 661 deletions(-) diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index 3599d0843..b52e0fbf6 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -35,7 +35,9 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message) @@ -224,6 +226,10 @@ void AMDemod::applySettings(const AMDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -413,6 +419,63 @@ void AMDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void AMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void AMDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const AMDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void AMDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const AMDemodSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); @@ -458,25 +521,6 @@ void AMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, con if (channelSettingsKeys.contains("streamIndex") || force) { swgAMDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void AMDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index 00ccf7e1c..280f24aa0 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -142,6 +142,13 @@ private: void applySettings(const AMDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const AMDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const AMDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demodbfm/bfmdemod.cpp b/plugins/channelrx/demodbfm/bfmdemod.cpp index cd2a5050f..284695cf3 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.cpp +++ b/plugins/channelrx/demodbfm/bfmdemod.cpp @@ -35,7 +35,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "bfmdemod.h" @@ -212,6 +214,10 @@ void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -439,10 +445,67 @@ void BFMDemod::webapiFormatRDSReport(SWGSDRangel::SWGRDSReport *report) void BFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const BFMDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void BFMDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const BFMDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void BFMDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const BFMDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("BFMDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setBfmDemodSettings(new SWGSDRangel::SWGBFMDemodSettings()); SWGSDRangel::SWGBFMDemodSettings *swgBFMDemodSettings = swgChannelSettings->getBfmDemodSettings(); @@ -487,25 +550,6 @@ void BFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex") || force) { swgBFMDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void BFMDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demodbfm/bfmdemod.h b/plugins/channelrx/demodbfm/bfmdemod.h index 7764226da..f0428a022 100644 --- a/plugins/channelrx/demodbfm/bfmdemod.h +++ b/plugins/channelrx/demodbfm/bfmdemod.h @@ -158,6 +158,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiFormatRDSReport(SWGSDRangel::SWGRDSReport *report); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const BFMDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const BFMDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const BFMDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demoddsd/dsddemod.cpp b/plugins/channelrx/demoddsd/dsddemod.cpp index 60196861a..be9eaea32 100644 --- a/plugins/channelrx/demoddsd/dsddemod.cpp +++ b/plugins/channelrx/demoddsd/dsddemod.cpp @@ -37,7 +37,9 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "dsddemod.h" @@ -250,6 +252,10 @@ void DSDDemod::applySettings(const DSDDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -487,10 +493,67 @@ void DSDDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response void DSDDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void DSDDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void DSDDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const DSDDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("DSDDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setDsdDemodSettings(new SWGSDRangel::SWGDSDDemodSettings()); SWGSDRangel::SWGDSDDemodSettings *swgDSDDemodSettings = swgChannelSettings->getDsdDemodSettings(); @@ -565,25 +628,6 @@ void DSDDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex") || force) { swgDSDDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void DSDDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demoddsd/dsddemod.h b/plugins/channelrx/demoddsd/dsddemod.h index 0d554bfcd..2a99ffa7c 100644 --- a/plugins/channelrx/demoddsd/dsddemod.h +++ b/plugins/channelrx/demoddsd/dsddemod.h @@ -140,6 +140,13 @@ private: void applySettings(const DSDDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const DSDDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demodfreedv/freedvdemod.cpp b/plugins/channelrx/demodfreedv/freedvdemod.cpp index 0e08e5f38..68d5e3fea 100644 --- a/plugins/channelrx/demodfreedv/freedvdemod.cpp +++ b/plugins/channelrx/demodfreedv/freedvdemod.cpp @@ -30,7 +30,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "freedvdemod.h" @@ -206,6 +208,10 @@ void FreeDVDemod::applySettings(const FreeDVDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -386,10 +392,67 @@ void FreeDVDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respo void FreeDVDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FreeDVDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void FreeDVDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreeDVDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("FreeDVDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setFreeDvDemodSettings(new SWGSDRangel::SWGFreeDVDemodSettings()); SWGSDRangel::SWGFreeDVDemodSettings *swgFreeDVDemodSettings = swgChannelSettings->getFreeDvDemodSettings(); @@ -428,25 +491,6 @@ void FreeDVDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, if (channelSettingsKeys.contains("streamIndex") || force) { swgFreeDVDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void FreeDVDemod::networkManagerFinished(QNetworkReply *reply) @@ -473,4 +517,4 @@ void FreeDVDemod::networkManagerFinished(QNetworkReply *reply) void FreeDVDemod::setLevelMeter(QObject *levelMeter) { connect(m_basebandSink, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int))); -} \ No newline at end of file +} diff --git a/plugins/channelrx/demodfreedv/freedvdemod.h b/plugins/channelrx/demodfreedv/freedvdemod.h index 532da4b2a..15bcd8eba 100644 --- a/plugins/channelrx/demodfreedv/freedvdemod.h +++ b/plugins/channelrx/demodfreedv/freedvdemod.h @@ -156,6 +156,13 @@ private: void applySettings(const FreeDVDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const FreeDVDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreeDVDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demodnfm/nfmdemod.cpp b/plugins/channelrx/demodnfm/nfmdemod.cpp index a5a5760fb..0b746ad83 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.cpp +++ b/plugins/channelrx/demodnfm/nfmdemod.cpp @@ -35,7 +35,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "nfmdemod.h" @@ -441,10 +443,67 @@ void NFMDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response void NFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void NFMDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const NFMDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void NFMDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const NFMDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("NFMDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setNfmDemodSettings(new SWGSDRangel::SWGNFMDemodSettings()); SWGSDRangel::SWGNFMDemodSettings *swgNFMDemodSettings = swgChannelSettings->getNfmDemodSettings(); @@ -498,25 +557,6 @@ void NFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex") || force) { swgNFMDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void NFMDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demodnfm/nfmdemod.h b/plugins/channelrx/demodnfm/nfmdemod.h index b17250c6f..b3386eb61 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.h +++ b/plugins/channelrx/demodnfm/nfmdemod.h @@ -138,6 +138,13 @@ private: void applySettings(const NFMDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const NFMDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const NFMDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index 5b370c8e5..49930de1a 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -36,7 +36,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "ssbdemod.h" @@ -235,6 +237,10 @@ void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -443,10 +449,67 @@ void SSBDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response void SSBDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void SSBDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void SSBDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const SSBDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("SSBDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setSsbDemodSettings(new SWGSDRangel::SWGSSBDemodSettings()); SWGSDRangel::SWGSSBDemodSettings *swgSSBDemodSettings = swgChannelSettings->getSsbDemodSettings(); @@ -506,25 +569,6 @@ void SSBDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex") || force) { swgSSBDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void SSBDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demodssb/ssbdemod.h b/plugins/channelrx/demodssb/ssbdemod.h index 05df4728b..51c21647a 100644 --- a/plugins/channelrx/demodssb/ssbdemod.h +++ b/plugins/channelrx/demodssb/ssbdemod.h @@ -141,6 +141,13 @@ private: void applySettings(const SSBDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const SSBDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const SSBDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/demodwfm/wfmdemod.cpp b/plugins/channelrx/demodwfm/wfmdemod.cpp index 5aaed7a18..371594600 100644 --- a/plugins/channelrx/demodwfm/wfmdemod.cpp +++ b/plugins/channelrx/demodwfm/wfmdemod.cpp @@ -38,7 +38,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "wfmdemod.h" @@ -211,6 +213,10 @@ void WFMDemod::applySettings(const WFMDemodSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -386,10 +392,67 @@ void WFMDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response void WFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const WFMDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void WFMDemod::featuresSendSettings(QList<QString>& channelSettingsKeys, const WFMDemodSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void WFMDemod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const WFMDemodSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("WFMDemod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setWfmDemodSettings(new SWGSDRangel::SWGWFMDemodSettings()); SWGSDRangel::SWGWFMDemodSettings *swgWFMDemodSettings = swgChannelSettings->getWfmDemodSettings(); @@ -425,25 +488,6 @@ void WFMDemod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex") || force) { swgWFMDemodSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void WFMDemod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/demodwfm/wfmdemod.h b/plugins/channelrx/demodwfm/wfmdemod.h index b0ba2f628..71ac9f15c 100644 --- a/plugins/channelrx/demodwfm/wfmdemod.h +++ b/plugins/channelrx/demodwfm/wfmdemod.h @@ -137,6 +137,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const WFMDemodSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const WFMDemodSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const WFMDemodSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/filesink/filesink.cpp b/plugins/channelrx/filesink/filesink.cpp index 288d0e989..52a91193a 100644 --- a/plugins/channelrx/filesink/filesink.cpp +++ b/plugins/channelrx/filesink/filesink.cpp @@ -35,6 +35,8 @@ #include "dsp/hbfilterchainconverter.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "filesinkmessages.h" #include "filesinkbaseband.h" @@ -293,6 +295,10 @@ void FileSink::applySettings(const FileSinkSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -522,10 +528,67 @@ void FileSink::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response void FileSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FileSinkSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FileSink::featuresSendSettings(QList<QString>& channelSettingsKeys, const FileSinkSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void FileSink::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FileSinkSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("FileSink")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setFileSinkSettings(new SWGSDRangel::SWGFileSinkSettings()); SWGSDRangel::SWGFileSinkSettings *swgFileSinkSettings = swgChannelSettings->getFileSinkSettings(); @@ -564,25 +627,6 @@ void FileSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, co if (channelSettingsKeys.contains("streamIndex")) { swgFileSinkSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void FileSink::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/filesink/filesink.h b/plugins/channelrx/filesink/filesink.h index 238742616..e60107e96 100644 --- a/plugins/channelrx/filesink/filesink.h +++ b/plugins/channelrx/filesink/filesink.h @@ -148,6 +148,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FileSinkSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const FileSinkSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FileSinkSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/freqtracker/freqtracker.cpp b/plugins/channelrx/freqtracker/freqtracker.cpp index 497a59ebb..0761cb3ca 100644 --- a/plugins/channelrx/freqtracker/freqtracker.cpp +++ b/plugins/channelrx/freqtracker/freqtracker.cpp @@ -41,6 +41,8 @@ #include "device/deviceapi.h" #include "util/db.h" #include "util/stepfunctions.h" +#include "feature/feature.h" +#include "maincore.h" #include "freqtrackerreport.h" @@ -256,6 +258,10 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -449,6 +455,62 @@ void FreqTracker::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respo void FreqTracker::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FreqTracker::featuresSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void FreqTracker::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreqTrackerSettings& settings, + bool force) +{ swgChannelSettings->setDirection(0); // single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); @@ -479,25 +541,6 @@ void FreqTracker::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, if (channelSettingsKeys.contains("streamIndex") || force) { swgFreqTrackerSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void FreqTracker::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/freqtracker/freqtracker.h b/plugins/channelrx/freqtracker/freqtracker.h index 224059e3b..e820ec619 100644 --- a/plugins/channelrx/freqtracker/freqtracker.h +++ b/plugins/channelrx/freqtracker/freqtracker.h @@ -139,6 +139,13 @@ private: void applySettings(const FreqTrackerSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const FreqTrackerSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreqTrackerSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/localsink/localsink.cpp b/plugins/channelrx/localsink/localsink.cpp index b1f62c4fe..a33a80997 100644 --- a/plugins/channelrx/localsink/localsink.cpp +++ b/plugins/channelrx/localsink/localsink.cpp @@ -33,6 +33,8 @@ #include "dsp/hbfilterchainconverter.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "localsinkbaseband.h" #include "localsink.h" @@ -302,6 +304,10 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -436,10 +442,67 @@ void LocalSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& res void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void LocalSink::featuresSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void LocalSink::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const LocalSinkSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("LocalSink")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setLocalSinkSettings(new SWGSDRangel::SWGLocalSinkSettings()); SWGSDRangel::SWGLocalSinkSettings *swgLocalSinkSettings = swgChannelSettings->getLocalSinkSettings(); @@ -466,25 +529,6 @@ void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c if (channelSettingsKeys.contains("streamIndex") || force) { swgLocalSinkSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void LocalSink::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/localsink/localsink.h b/plugins/channelrx/localsink/localsink.h index 7da9107c0..d2eca5839 100644 --- a/plugins/channelrx/localsink/localsink.h +++ b/plugins/channelrx/localsink/localsink.h @@ -154,6 +154,13 @@ private: DeviceSampleSource *getLocalDevice(uint32_t index); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const LocalSinkSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/remotesink/remotesink.cpp b/plugins/channelrx/remotesink/remotesink.cpp index 34bdcf5ce..548e0a912 100644 --- a/plugins/channelrx/remotesink/remotesink.cpp +++ b/plugins/channelrx/remotesink/remotesink.cpp @@ -36,6 +36,8 @@ #include "dsp/devicesamplemimo.h" #include "dsp/dspdevicesourceengine.h" #include "device/deviceapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "remotesinkbaseband.h" @@ -236,6 +238,10 @@ void RemoteSink::applySettings(const RemoteSinkSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; if (frequencyOffsetChange) { @@ -415,10 +421,67 @@ void RemoteSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& re void RemoteSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSinkSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void RemoteSink::featuresSendSettings(QList<QString>& channelSettingsKeys, const RemoteSinkSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void RemoteSink::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RemoteSinkSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("RemoteSink")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setRemoteSinkSettings(new SWGSDRangel::SWGRemoteSinkSettings()); SWGSDRangel::SWGRemoteSinkSettings *swgRemoteSinkSettings = swgChannelSettings->getRemoteSinkSettings(); @@ -452,25 +515,6 @@ void RemoteSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, if (channelSettingsKeys.contains("streamIndex") || force) { swgRemoteSinkSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void RemoteSink::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channelrx/remotesink/remotesink.h b/plugins/channelrx/remotesink/remotesink.h index 61a02f8b6..424a00860 100644 --- a/plugins/channelrx/remotesink/remotesink.h +++ b/plugins/channelrx/remotesink/remotesink.h @@ -133,6 +133,13 @@ private: static void validateFilterChainHash(RemoteSinkSettings& settings); void calculateFrequencyOffset(); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSinkSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const RemoteSinkSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RemoteSinkSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/udpsink/udpsink.cpp b/plugins/channelrx/udpsink/udpsink.cpp index a596005ea..7a0882f0f 100644 --- a/plugins/channelrx/udpsink/udpsink.cpp +++ b/plugins/channelrx/udpsink/udpsink.cpp @@ -33,6 +33,8 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "udpsink.h" @@ -236,6 +238,10 @@ void UDPSink::applySettings(const UDPSinkSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -448,10 +454,67 @@ void UDPSink::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void UDPSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const UDPSinkSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(0); // single sink (Rx) + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void UDPSink::featuresSendSettings(QList<QString>& channelSettingsKeys, const UDPSinkSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void UDPSink::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const UDPSinkSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("UDPSink")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setUdpSinkSettings(new SWGSDRangel::SWGUDPSinkSettings()); SWGSDRangel::SWGUDPSinkSettings *swgUDPSinkSettings = swgChannelSettings->getUdpSinkSettings(); @@ -517,25 +580,6 @@ void UDPSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, con if (channelSettingsKeys.contains("streamIndex") || force) { swgUDPSinkSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void UDPSink::networkManagerFinished(QNetworkReply *reply) @@ -563,4 +607,4 @@ void UDPSink::enableSpectrum(bool enable) { UDPSinkBaseband::MsgEnableSpectrum *msg = UDPSinkBaseband::MsgEnableSpectrum::create(enable); m_basebandSink->getInputMessageQueue()->push(msg); -} \ No newline at end of file +} diff --git a/plugins/channelrx/udpsink/udpsink.h b/plugins/channelrx/udpsink/udpsink.h index b98f16c75..b52472835 100644 --- a/plugins/channelrx/udpsink/udpsink.h +++ b/plugins/channelrx/udpsink/udpsink.h @@ -145,6 +145,13 @@ protected: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const UDPSinkSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const UDPSinkSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const UDPSinkSettings& settings, + bool force + ); }; #endif // INCLUDE_UDPSINK_H diff --git a/plugins/channeltx/filesource/filesource.cpp b/plugins/channeltx/filesource/filesource.cpp index 5e9a3e453..d4f995319 100644 --- a/plugins/channeltx/filesource/filesource.cpp +++ b/plugins/channeltx/filesource/filesource.cpp @@ -33,7 +33,9 @@ #include "dsp/devicesamplesink.h" #include "dsp/hbfilterchainconverter.h" #include "dsp/filerecord.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "filesourcebaseband.h" @@ -261,6 +263,10 @@ void FileSource::applySettings(const FileSourceSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -498,10 +504,67 @@ void FileSource::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respon void FileSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FileSourceSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FileSource::featuresSendSettings(QList<QString>& channelSettingsKeys, const FileSourceSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void FileSource::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FileSourceSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("FileSource")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setFileSourceSettings(new SWGSDRangel::SWGFileSourceSettings()); SWGSDRangel::SWGFileSourceSettings *swgFileSourceSettings = swgChannelSettings->getFileSourceSettings(); @@ -525,25 +588,6 @@ void FileSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, if (channelSettingsKeys.contains("streamIndex") || force) { swgFileSourceSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void FileSource::networkManagerFinished(QNetworkReply *reply) @@ -585,4 +629,4 @@ double FileSource::getMagSq() const uint32_t FileSource::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSinkStreams(); -} \ No newline at end of file +} diff --git a/plugins/channeltx/filesource/filesource.h b/plugins/channeltx/filesource/filesource.h index a1ae86a8e..a217ac87d 100644 --- a/plugins/channeltx/filesource/filesource.h +++ b/plugins/channeltx/filesource/filesource.h @@ -254,6 +254,13 @@ private: void calculateFrequencyOffset(); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FileSourceSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const FileSourceSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FileSourceSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/localsource/localsource.cpp b/plugins/channeltx/localsource/localsource.cpp index 8ef035656..889c38ce1 100644 --- a/plugins/channeltx/localsource/localsource.cpp +++ b/plugins/channeltx/localsource/localsource.cpp @@ -31,6 +31,8 @@ #include "dsp/devicesamplesink.h" #include "dsp/hbfilterchainconverter.h" #include "device/deviceapi.h" +#include "feature/feature.h" +#include "maincore.h" #include "localsourcebaseband.h" @@ -305,6 +307,10 @@ void LocalSource::applySettings(const LocalSourceSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -438,10 +444,67 @@ void LocalSource::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& r void LocalSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void LocalSource::featuresSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void LocalSource::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const LocalSourceSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("LocalSource")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setLocalSourceSettings(new SWGSDRangel::SWGLocalSourceSettings()); SWGSDRangel::SWGLocalSourceSettings *swgLocalSourceSettings = swgChannelSettings->getLocalSourceSettings(); @@ -468,25 +531,6 @@ void LocalSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, if (channelSettingsKeys.contains("streamIndex") || force) { swgLocalSourceSettings->setRgbColor(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void LocalSource::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channeltx/localsource/localsource.h b/plugins/channeltx/localsource/localsource.h index 38cafc5e1..d53436c65 100644 --- a/plugins/channeltx/localsource/localsource.h +++ b/plugins/channeltx/localsource/localsource.h @@ -152,6 +152,13 @@ private: DeviceSampleSink *getLocalDevice(uint32_t index); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const LocalSourceSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.cpp b/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.cpp index 1003fb800..af9dcb8c6 100644 --- a/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.cpp +++ b/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.cpp @@ -38,8 +38,10 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" #include "util/crc.h" +#include "maincore.h" #include "ieee_802_15_4_modbaseband.h" #include "ieee_802_15_4_mod.h" @@ -217,6 +219,10 @@ void IEEE_802_15_4_Mod::applySettings(const IEEE_802_15_4_ModSettings& settings, webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -423,10 +429,67 @@ void IEEE_802_15_4_Mod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& void IEEE_802_15_4_Mod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const IEEE_802_15_4_ModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void IEEE_802_15_4_Mod::featuresSendSettings(QList<QString>& channelSettingsKeys, const IEEE_802_15_4_ModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void IEEE_802_15_4_Mod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const IEEE_802_15_4_ModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("IEEE_802_15_4_Mod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setIeee802154ModSettings(new SWGSDRangel::SWGIEEE_802_15_4_ModSettings()); SWGSDRangel::SWGIEEE_802_15_4_ModSettings *swgIEEE_802_15_4_ModSettings = swgChannelSettings->getIeee802154ModSettings(); @@ -462,25 +525,6 @@ void IEEE_802_15_4_Mod::webapiReverseSendSettings(QList<QString>& channelSetting if (channelSettingsKeys.contains("streamIndex") || force) { swgIEEE_802_15_4_ModSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void IEEE_802_15_4_Mod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.h b/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.h index 3e3c82dcc..3937bb79f 100644 --- a/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.h +++ b/plugins/channeltx/mod802.15.4/ieee_802_15_4_mod.h @@ -168,6 +168,13 @@ private: void applySettings(const IEEE_802_15_4_ModSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const IEEE_802_15_4_ModSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const IEEE_802_15_4_ModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const IEEE_802_15_4_ModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index 9684a16de..577469b86 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -35,7 +35,9 @@ #include "dsp/devicesamplemimo.h" #include "dsp/cwkeyer.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "ammodbaseband.h" #include "ammod.h" @@ -300,6 +302,10 @@ void AMMod::applySettings(const AMModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -502,59 +508,7 @@ void AMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void AMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(1); // single source (Tx) - swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); - swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("AMMod")); - swgChannelSettings->setAmModSettings(new SWGSDRangel::SWGAMModSettings()); - SWGSDRangel::SWGAMModSettings *swgAMModSettings = swgChannelSettings->getAmModSettings(); - - // transfer data that has been modified. When force is on transfer all data except reverse API data - - if (channelSettingsKeys.contains("channelMute") || force) { - swgAMModSettings->setChannelMute(settings.m_channelMute ? 1 : 0); - } - if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { - swgAMModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); - } - if (channelSettingsKeys.contains("modAFInput") || force) { - swgAMModSettings->setModAfInput((int) settings.m_modAFInput); - } - if (channelSettingsKeys.contains("audioDeviceName") || force) { - swgAMModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); - } - if (channelSettingsKeys.contains("playLoop") || force) { - swgAMModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0); - } - if (channelSettingsKeys.contains("rfBandwidth") || force) { - swgAMModSettings->setRfBandwidth(settings.m_rfBandwidth); - } - if (channelSettingsKeys.contains("rgbColor") || force) { - swgAMModSettings->setRgbColor(settings.m_rgbColor); - } - if (channelSettingsKeys.contains("title") || force) { - swgAMModSettings->setTitle(new QString(settings.m_title)); - } - if (channelSettingsKeys.contains("toneFrequency") || force) { - swgAMModSettings->setToneFrequency(settings.m_toneFrequency); - } - if (channelSettingsKeys.contains("volumeFactor") || force) { - swgAMModSettings->setVolumeFactor(settings.m_volumeFactor); - } - if (channelSettingsKeys.contains("modFactor") || force) { - swgAMModSettings->setModFactor(settings.m_modFactor); - } - if (channelSettingsKeys.contains("streamIndex") || force) { - swgAMModSettings->setStreamIndex(settings.m_streamIndex); - } - - if (force) - { - const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); - swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); - SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); - } + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") .arg(settings.m_reverseAPIAddress) @@ -608,6 +562,96 @@ void AMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) delete swgChannelSettings; } +void AMMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void AMMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const AMModSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(1); // single source (Tx) + swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); + swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); + swgChannelSettings->setChannelType(new QString(m_channelId)); + swgChannelSettings->setAmModSettings(new SWGSDRangel::SWGAMModSettings()); + SWGSDRangel::SWGAMModSettings *swgAMModSettings = swgChannelSettings->getAmModSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("channelMute") || force) { + swgAMModSettings->setChannelMute(settings.m_channelMute ? 1 : 0); + } + if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { + swgAMModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + } + if (channelSettingsKeys.contains("modAFInput") || force) { + swgAMModSettings->setModAfInput((int) settings.m_modAFInput); + } + if (channelSettingsKeys.contains("audioDeviceName") || force) { + swgAMModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); + } + if (channelSettingsKeys.contains("playLoop") || force) { + swgAMModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0); + } + if (channelSettingsKeys.contains("rfBandwidth") || force) { + swgAMModSettings->setRfBandwidth(settings.m_rfBandwidth); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgAMModSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgAMModSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("toneFrequency") || force) { + swgAMModSettings->setToneFrequency(settings.m_toneFrequency); + } + if (channelSettingsKeys.contains("volumeFactor") || force) { + swgAMModSettings->setVolumeFactor(settings.m_volumeFactor); + } + if (channelSettingsKeys.contains("modFactor") || force) { + swgAMModSettings->setModFactor(settings.m_modFactor); + } + if (channelSettingsKeys.contains("streamIndex") || force) { + swgAMModSettings->setStreamIndex(settings.m_streamIndex); + } + + if (force) + { + const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); + swgAMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); + SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgAMModSettings->getCwKeyer(); + m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + } +} + void AMMod::networkManagerFinished(QNetworkReply *reply) { QNetworkReply::NetworkError replyError = reply->error(); diff --git a/plugins/channeltx/modam/ammod.h b/plugins/channeltx/modam/ammod.h index edf4558a5..25a4c019e 100644 --- a/plugins/channeltx/modam/ammod.h +++ b/plugins/channeltx/modam/ammod.h @@ -261,6 +261,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force); void webapiReverseSendCWSettings(const CWKeyerSettings& settings); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const AMModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const AMModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index 467843cd9..fdf157bbf 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -34,7 +34,9 @@ #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "atvmodbaseband.h" #include "atvmod.h" @@ -320,6 +322,10 @@ void ATVMod::applySettings(const ATVModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -583,10 +589,67 @@ void ATVMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void ATVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const ATVModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void ATVMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const ATVModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void ATVMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const ATVModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("ATVMod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setAtvModSettings(new SWGSDRangel::SWGATVModSettings()); SWGSDRangel::SWGATVModSettings *swgATVModSettings = swgChannelSettings->getAtvModSettings(); @@ -658,25 +721,6 @@ void ATVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons if (channelSettingsKeys.contains("streamIndex") || force) { swgATVModSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void ATVMod::networkManagerFinished(QNetworkReply *reply) @@ -723,4 +767,4 @@ void ATVMod::getCameraNumbers(std::vector<int>& numbers) void ATVMod::propagateMessageQueueToGUI() { m_basebandSource->setMessageQueueToGUI(getMessageQueueToGUI()); -} \ No newline at end of file +} diff --git a/plugins/channeltx/modatv/atvmod.h b/plugins/channeltx/modatv/atvmod.h index 5556dde4a..a6caa8136 100644 --- a/plugins/channeltx/modatv/atvmod.h +++ b/plugins/channeltx/modatv/atvmod.h @@ -317,6 +317,13 @@ private: void applySettings(const ATVModSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const ATVModSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const ATVModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const ATVModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modfreedv/freedvmod.cpp b/plugins/channeltx/modfreedv/freedvmod.cpp index 06f3c4944..98fe967a7 100644 --- a/plugins/channeltx/modfreedv/freedvmod.cpp +++ b/plugins/channeltx/modfreedv/freedvmod.cpp @@ -34,7 +34,9 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "freedvmodbaseband.h" #include "freedvmod.h" @@ -288,6 +290,10 @@ void FreeDVMod::applySettings(const FreeDVModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -494,10 +500,99 @@ void FreeDVMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons void FreeDVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FreeDVMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + swgChannelSettings->setDirection(1); // single source (Tx) + swgChannelSettings->setChannelType(new QString("FreeDVMod")); + swgChannelSettings->setFreeDvModSettings(new SWGSDRangel::SWGFreeDVModSettings()); + SWGSDRangel::SWGFreeDVModSettings *swgFreeDVModSettings = swgChannelSettings->getFreeDvModSettings(); + + swgFreeDVModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); + SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgFreeDVModSettings->getCwKeyer(); + m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex) + .arg(m_settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void FreeDVMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const FreeDVModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void FreeDVMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreeDVModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("FreeDVMod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setFreeDvModSettings(new SWGSDRangel::SWGFreeDVModSettings()); SWGSDRangel::SWGFreeDVModSettings *swgFreeDVModSettings = swgChannelSettings->getFreeDvModSettings(); @@ -550,57 +645,6 @@ void FreeDVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgFreeDVModSettings->getCwKeyer(); m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; -} - -void FreeDVMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) -{ - SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(1); // single source (Tx) - swgChannelSettings->setChannelType(new QString("FreeDVMod")); - swgChannelSettings->setFreeDvModSettings(new SWGSDRangel::SWGFreeDVModSettings()); - SWGSDRangel::SWGFreeDVModSettings *swgFreeDVModSettings = swgChannelSettings->getFreeDvModSettings(); - - swgFreeDVModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); - SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgFreeDVModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(m_settings.m_reverseAPIAddress) - .arg(m_settings.m_reverseAPIPort) - .arg(m_settings.m_reverseAPIDeviceIndex) - .arg(m_settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void FreeDVMod::networkManagerFinished(QNetworkReply *reply) @@ -662,4 +706,4 @@ void FreeDVMod::setLevelMeter(QObject *levelMeter) uint32_t FreeDVMod::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSinkStreams(); -} \ No newline at end of file +} diff --git a/plugins/channeltx/modfreedv/freedvmod.h b/plugins/channeltx/modfreedv/freedvmod.h index f1601b872..758547d6e 100644 --- a/plugins/channeltx/modfreedv/freedvmod.h +++ b/plugins/channeltx/modfreedv/freedvmod.h @@ -269,6 +269,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVModSettings& settings, bool force); void webapiReverseSendCWSettings(const CWKeyerSettings& settings); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const FreeDVModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const FreeDVModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modnfm/nfmmod.cpp b/plugins/channeltx/modnfm/nfmmod.cpp index 2047fd222..5227ccf98 100644 --- a/plugins/channeltx/modnfm/nfmmod.cpp +++ b/plugins/channeltx/modnfm/nfmmod.cpp @@ -36,7 +36,9 @@ #include "dsp/dspcommands.h" #include "dsp/cwkeyer.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "nfmmodbaseband.h" #include "nfmmod.h" @@ -346,6 +348,10 @@ void NFMMod::applySettings(const NFMModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -556,10 +562,99 @@ void NFMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void NFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + swgChannelSettings->setDirection(1); // single source (Tx) + swgChannelSettings->setChannelType(new QString("NFMMod")); + swgChannelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings()); + SWGSDRangel::SWGNFMModSettings *swgNFModSettings = swgChannelSettings->getNfmModSettings(); + + swgNFModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); + SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgNFModSettings->getCwKeyer(); + m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex) + .arg(m_settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void NFMMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void NFMMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const NFMModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("NFMMod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings()); SWGSDRangel::SWGNFMModSettings *swgNFMModSettings = swgChannelSettings->getNfmModSettings(); @@ -618,57 +713,6 @@ void NFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgNFMModSettings->getCwKeyer(); m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; -} - -void NFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) -{ - SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(1); // single source (Tx) - swgChannelSettings->setChannelType(new QString("NFMMod")); - swgChannelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings()); - SWGSDRangel::SWGNFMModSettings *swgNFModSettings = swgChannelSettings->getNfmModSettings(); - - swgNFModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); - SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgNFModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(m_settings.m_reverseAPIAddress) - .arg(m_settings.m_reverseAPIPort) - .arg(m_settings.m_reverseAPIDeviceIndex) - .arg(m_settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void NFMMod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channeltx/modnfm/nfmmod.h b/plugins/channeltx/modnfm/nfmmod.h index 875af3328..ff3abb104 100644 --- a/plugins/channeltx/modnfm/nfmmod.h +++ b/plugins/channeltx/modnfm/nfmmod.h @@ -261,6 +261,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force); void webapiReverseSendCWSettings(const CWKeyerSettings& settings); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const NFMModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const NFMModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modpacket/packetmod.cpp b/plugins/channeltx/modpacket/packetmod.cpp index 141c1214e..4a14c0d10 100644 --- a/plugins/channeltx/modpacket/packetmod.cpp +++ b/plugins/channeltx/modpacket/packetmod.cpp @@ -38,8 +38,10 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" #include "util/crc.h" +#include "maincore.h" #include "packetmodbaseband.h" #include "packetmod.h" @@ -344,6 +346,10 @@ void PacketMod::applySettings(const PacketModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -703,10 +709,67 @@ void PacketMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons void PacketMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void PacketMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void PacketMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const PacketModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("PacketMod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setPacketModSettings(new SWGSDRangel::SWGPacketModSettings()); SWGSDRangel::SWGPacketModSettings *swgPacketModSettings = swgChannelSettings->getPacketModSettings(); @@ -835,25 +898,6 @@ void PacketMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c if (channelSettingsKeys.contains("streamIndex") || force) { swgPacketModSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void PacketMod::networkManagerFinished(QNetworkReply *reply) diff --git a/plugins/channeltx/modpacket/packetmod.h b/plugins/channeltx/modpacket/packetmod.h index 972b080f1..c28276a25 100644 --- a/plugins/channeltx/modpacket/packetmod.h +++ b/plugins/channeltx/modpacket/packetmod.h @@ -179,6 +179,13 @@ private: void applySettings(const PacketModSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const PacketModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index 8bdcc32a0..898570dc1 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -35,7 +35,9 @@ #include "dsp/dspcommands.h" #include "dsp/cwkeyer.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "ssbmodbaseband.h" #include "ssbmod.h" @@ -305,6 +307,10 @@ void SSBMod::applySettings(const SSBModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; m_settings.m_bandwidth = band; m_settings.m_lowCutoff = lowCutoff; @@ -534,10 +540,99 @@ void SSBMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void SSBMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + swgChannelSettings->setDirection(1); // single source (Tx) + swgChannelSettings->setChannelType(new QString("SSBMod")); + swgChannelSettings->setSsbModSettings(new SWGSDRangel::SWGSSBModSettings()); + SWGSDRangel::SWGSSBModSettings *swgSSBModSettings = swgChannelSettings->getSsbModSettings(); + + swgSSBModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); + SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgSSBModSettings->getCwKeyer(); + m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex) + .arg(m_settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void SSBMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void SSBMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const SSBModSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("SSBMod")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setSsbModSettings(new SWGSDRangel::SWGSSBModSettings()); SWGSDRangel::SWGSSBModSettings *swgSSBModSettings = swgChannelSettings->getSsbModSettings(); @@ -605,57 +700,6 @@ void SSBMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, cons SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgSSBModSettings->getCwKeyer(); m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; -} - -void SSBMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) -{ - SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(1); // single source (Tx) - swgChannelSettings->setChannelType(new QString("SSBMod")); - swgChannelSettings->setSsbModSettings(new SWGSDRangel::SWGSSBModSettings()); - SWGSDRangel::SWGSSBModSettings *swgSSBModSettings = swgChannelSettings->getSsbModSettings(); - - swgSSBModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); - SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgSSBModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(m_settings.m_reverseAPIAddress) - .arg(m_settings.m_reverseAPIPort) - .arg(m_settings.m_reverseAPIDeviceIndex) - .arg(m_settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void SSBMod::networkManagerFinished(QNetworkReply *reply) @@ -707,4 +751,4 @@ int SSBMod::getFeedbackAudioSampleRate() const uint32_t SSBMod::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSinkStreams(); -} \ No newline at end of file +} diff --git a/plugins/channeltx/modssb/ssbmod.h b/plugins/channeltx/modssb/ssbmod.h index 8f3913989..16088a26e 100644 --- a/plugins/channeltx/modssb/ssbmod.h +++ b/plugins/channeltx/modssb/ssbmod.h @@ -265,6 +265,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force); void webapiReverseSendCWSettings(const CWKeyerSettings& settings); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const SSBModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const SSBModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/modwfm/wfmmod.cpp b/plugins/channeltx/modwfm/wfmmod.cpp index ca65ae8bd..1bac328b9 100644 --- a/plugins/channeltx/modwfm/wfmmod.cpp +++ b/plugins/channeltx/modwfm/wfmmod.cpp @@ -34,7 +34,9 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "wfmmodbaseband.h" #include "wfmmod.h" @@ -286,6 +288,10 @@ void WFMMod::applySettings(const WFMModSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -489,62 +495,7 @@ void WFMMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) void WFMMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const WFMModSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); - swgChannelSettings->setDirection(1); // single source (Tx) - swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); - swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("WFMMod")); - swgChannelSettings->setWfmModSettings(new SWGSDRangel::SWGWFMModSettings()); - SWGSDRangel::SWGWFMModSettings *swgWFMModSettings = swgChannelSettings->getWfmModSettings(); - - // transfer data that has been modified. When force is on transfer all data except reverse API data - - if (channelSettingsKeys.contains("channelMute") || force) { - swgWFMModSettings->setChannelMute(settings.m_channelMute ? 1 : 0); - } - if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { - swgWFMModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); - } - if (channelSettingsKeys.contains("modAFInput") || force) { - swgWFMModSettings->setModAfInput((int) settings.m_modAFInput); - } - if (channelSettingsKeys.contains("playLoop") || force) { - swgWFMModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0); - } - if (channelSettingsKeys.contains("rfBandwidth") || force) { - swgWFMModSettings->setRfBandwidth(settings.m_rfBandwidth); - } - if (channelSettingsKeys.contains("afBandwidth") || force) { - swgWFMModSettings->setAfBandwidth(settings.m_afBandwidth); - } - if (channelSettingsKeys.contains("rgbColor") || force) { - swgWFMModSettings->setRgbColor(settings.m_rgbColor); - } - if (channelSettingsKeys.contains("title") || force) { - swgWFMModSettings->setTitle(new QString(settings.m_title)); - } - if (channelSettingsKeys.contains("toneFrequency") || force) { - swgWFMModSettings->setToneFrequency(settings.m_toneFrequency); - } - if (channelSettingsKeys.contains("volumeFactor") || force) { - swgWFMModSettings->setVolumeFactor(settings.m_volumeFactor); - } - if (channelSettingsKeys.contains("fmDeviation")) { - swgWFMModSettings->setFmDeviation(settings.m_fmDeviation); - } - if (channelSettingsKeys.contains("streamIndex")) { - swgWFMModSettings->setStreamIndex(settings.m_streamIndex); - } - if (channelSettingsKeys.contains("audioDeviceName") || force) { - swgWFMModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); - } - - if (force) - { - const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); - swgWFMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); - SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgWFMModSettings->getCwKeyer(); - m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); - } + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") .arg(settings.m_reverseAPIAddress) @@ -598,6 +549,99 @@ void WFMMod::webapiReverseSendCWSettings(const CWKeyerSettings& cwKeyerSettings) delete swgChannelSettings; } +void WFMMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const WFMModSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void WFMMod::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const WFMModSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(1); // single source (Tx) + swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); + swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); + swgChannelSettings->setChannelType(new QString(m_channelId)); + swgChannelSettings->setWfmModSettings(new SWGSDRangel::SWGWFMModSettings()); + SWGSDRangel::SWGWFMModSettings *swgWFMModSettings = swgChannelSettings->getWfmModSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("channelMute") || force) { + swgWFMModSettings->setChannelMute(settings.m_channelMute ? 1 : 0); + } + if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { + swgWFMModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + } + if (channelSettingsKeys.contains("modAFInput") || force) { + swgWFMModSettings->setModAfInput((int) settings.m_modAFInput); + } + if (channelSettingsKeys.contains("playLoop") || force) { + swgWFMModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0); + } + if (channelSettingsKeys.contains("rfBandwidth") || force) { + swgWFMModSettings->setRfBandwidth(settings.m_rfBandwidth); + } + if (channelSettingsKeys.contains("afBandwidth") || force) { + swgWFMModSettings->setAfBandwidth(settings.m_afBandwidth); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgWFMModSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgWFMModSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("toneFrequency") || force) { + swgWFMModSettings->setToneFrequency(settings.m_toneFrequency); + } + if (channelSettingsKeys.contains("volumeFactor") || force) { + swgWFMModSettings->setVolumeFactor(settings.m_volumeFactor); + } + if (channelSettingsKeys.contains("fmDeviation")) { + swgWFMModSettings->setFmDeviation(settings.m_fmDeviation); + } + if (channelSettingsKeys.contains("streamIndex")) { + swgWFMModSettings->setStreamIndex(settings.m_streamIndex); + } + if (channelSettingsKeys.contains("audioDeviceName") || force) { + swgWFMModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); + } + + if (force) + { + const CWKeyerSettings& cwKeyerSettings = m_basebandSource->getCWKeyer().getSettings(); + swgWFMModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings()); + SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgWFMModSettings->getCwKeyer(); + m_basebandSource->getCWKeyer().webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings); + } +} + void WFMMod::networkManagerFinished(QNetworkReply *reply) { QNetworkReply::NetworkError replyError = reply->error(); diff --git a/plugins/channeltx/modwfm/wfmmod.h b/plugins/channeltx/modwfm/wfmmod.h index 4b6e0696f..fee868cae 100644 --- a/plugins/channeltx/modwfm/wfmmod.h +++ b/plugins/channeltx/modwfm/wfmmod.h @@ -273,6 +273,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const WFMModSettings& settings, bool force); void webapiReverseSendCWSettings(const CWKeyerSettings& settings); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const WFMModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const WFMModSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/remotesource/remotesource.cpp b/plugins/channeltx/remotesource/remotesource.cpp index 180f90cdb..2a81cb6b1 100644 --- a/plugins/channeltx/remotesource/remotesource.cpp +++ b/plugins/channeltx/remotesource/remotesource.cpp @@ -29,7 +29,10 @@ #include "dsp/devicesamplesink.h" #include "device/deviceapi.h" +#include "feature/feature.h" #include "util/timeutil.h" +#include "util/db.h" +#include "maincore.h" #include "remotesourcebaseband.h" @@ -202,6 +205,10 @@ void RemoteSource::applySettings(const RemoteSourceSettings& settings, bool forc webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -350,10 +357,67 @@ void RemoteSource::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& resp void RemoteSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSourceSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void RemoteSource::featuresSendSettings(QList<QString>& channelSettingsKeys, const RemoteSourceSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void RemoteSource::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RemoteSourceSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("RemoteSource")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setRemoteSourceSettings(new SWGSDRangel::SWGRemoteSourceSettings()); SWGSDRangel::SWGRemoteSourceSettings *swgRemoteSourceSettings = swgChannelSettings->getRemoteSourceSettings(); @@ -374,25 +438,6 @@ void RemoteSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys if (channelSettingsKeys.contains("streamIndex") || force) { swgRemoteSourceSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void RemoteSource::networkManagerFinished(QNetworkReply *reply) @@ -419,4 +464,4 @@ void RemoteSource::networkManagerFinished(QNetworkReply *reply) uint32_t RemoteSource::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSinkStreams(); -} \ No newline at end of file +} diff --git a/plugins/channeltx/remotesource/remotesource.h b/plugins/channeltx/remotesource/remotesource.h index 41b9519cc..5ecce8b91 100644 --- a/plugins/channeltx/remotesource/remotesource.h +++ b/plugins/channeltx/remotesource/remotesource.h @@ -222,6 +222,13 @@ private: void applySettings(const RemoteSourceSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSourceSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const RemoteSourceSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RemoteSourceSettings& settings, + bool force + ); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channeltx/udpsource/udpsource.cpp b/plugins/channeltx/udpsource/udpsource.cpp index 8165c5b15..c2f5dc437 100644 --- a/plugins/channeltx/udpsource/udpsource.cpp +++ b/plugins/channeltx/udpsource/udpsource.cpp @@ -27,7 +27,9 @@ #include "device/deviceapi.h" #include "dsp/dspcommands.h" +#include "feature/feature.h" #include "util/db.h" +#include "maincore.h" #include "udpsourcebaseband.h" #include "udpsource.h" @@ -251,6 +253,10 @@ void UDPSource::applySettings(const UDPSourceSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + m_settings = settings; } @@ -484,10 +490,67 @@ void UDPSource::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons void UDPSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const UDPSourceSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgChannelSettings->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 swgChannelSettings; +} + +void UDPSource::featuresSendSettings(QList<QString>& channelSettingsKeys, const UDPSourceSettings& settings, bool force) +{ + QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void UDPSource::webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const UDPSourceSettings& settings, + bool force +) +{ swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("UDPSource")); + swgChannelSettings->setChannelType(new QString(m_channelId)); swgChannelSettings->setUdpSourceSettings(new SWGSDRangel::SWGUDPSourceSettings()); SWGSDRangel::SWGUDPSourceSettings *swgUDPSourceSettings = swgChannelSettings->getUdpSourceSettings(); @@ -559,25 +622,6 @@ void UDPSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c if (channelSettingsKeys.contains("streamIndex") || force) { swgUDPSourceSettings->setStreamIndex(settings.m_streamIndex); } - - QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") - .arg(settings.m_reverseAPIAddress) - .arg(settings.m_reverseAPIPort) - .arg(settings.m_reverseAPIDeviceIndex) - .arg(settings.m_reverseAPIChannelIndex); - m_networkRequest.setUrl(QUrl(channelSettingsURL)); - m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QBuffer *buffer = new QBuffer(); - buffer->open((QBuffer::ReadWrite)); - buffer->write(swgChannelSettings->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 swgChannelSettings; } void UDPSource::networkManagerFinished(QNetworkReply *reply) @@ -628,4 +672,4 @@ bool UDPSource::getSquelchOpen() const uint32_t UDPSource::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSinkStreams(); -} \ No newline at end of file +} diff --git a/plugins/channeltx/udpsource/udpsource.h b/plugins/channeltx/udpsource/udpsource.h index 72db40759..16d95dec1 100644 --- a/plugins/channeltx/udpsource/udpsource.h +++ b/plugins/channeltx/udpsource/udpsource.h @@ -176,6 +176,13 @@ private: void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const UDPSourceSettings& settings, bool force); + void featuresSendSettings(QList<QString>& channelSettingsKeys, const UDPSourceSettings& settings, bool force); + void webapiFormatChannelSettings( + QList<QString>& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const UDPSourceSettings& settings, + bool force + ); }; From c6699562f4bd32e205167ee5db60e1a6c7634989 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Fri, 23 Oct 2020 08:32:26 +0200 Subject: [PATCH 08/27] AFC: fixed transverter correction --- plugins/feature/afc/afcworker.cpp | 16 +++++++++++++--- plugins/feature/afc/afcworker.h | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index c4471181c..731765e3d 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -260,7 +260,7 @@ void AFCWorker::processChannelSettings( if (mainCore->existsChannel(it.key())) { int channelOffset = it.value().m_channelOffset + m_trackerChannelOffset - it.value().m_trackerOffset; - updateChannelOffset(it.key(),it.value().m_channelDirection, channelOffset); + updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); } else { @@ -286,7 +286,7 @@ void AFCWorker::processChannelSettings( } } -void AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset) +bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset) { SWGSDRangel::SWGChannelSettings swgChannelSettings; SWGSDRangel::SWGErrorResponse errorResponse; @@ -315,9 +315,13 @@ void AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int o errorResponse ); - if (httpRC / 100 != 2) { + if (httpRC / 100 != 2) + { qDebug() << "AFCWorker::updateChannelOffset: error code" << httpRC << ":" << *errorResponse.getMessage(); + return false; } + + return true; } void AFCWorker::updateTarget() @@ -364,6 +368,7 @@ void AFCWorker::updateTarget() QJsonObject *jsonObj = resDevice.asJsonObject(); QJsonValue xverterFrequencyValue; + // adjust transverter if (WebAPIUtils::extractValue(*jsonObj, "transverterDeltaFrequency", xverterFrequencyValue)) { double xverterFrequency = xverterFrequencyValue.toDouble(); @@ -374,6 +379,11 @@ void AFCWorker::updateTarget() qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; return; } + + // adjust tracker offset + if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction)) { + m_trackerChannelOffset += correction; + } } else // act on device { diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index 744523bc0..38bf4df24 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -136,7 +136,7 @@ private: const QList<QString> &channelSettingsKeys, SWGSDRangel::SWGChannelSettings *swgChannelSettings ); - void updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset); + bool updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset); void updateTarget(); bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); int getDeviceDirection(DeviceAPI *deviceAPI); From 6ff2c603c283c7431cd185460269a350ea4d5ea7 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 10:33:15 +0200 Subject: [PATCH 09/27] New left arrow icon --- sdrgui/resources/arrow_left.png | Bin 0 -> 724 bytes sdrgui/resources/res.qrc | 1 + 2 files changed, 1 insertion(+) create mode 100644 sdrgui/resources/arrow_left.png diff --git a/sdrgui/resources/arrow_left.png b/sdrgui/resources/arrow_left.png new file mode 100644 index 0000000000000000000000000000000000000000..4445d0ac203a4ea6ba4bfc6e47b2406e39a0b705 GIT binary patch literal 724 zcmV;_0xSKAP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv0004nX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ?*hm4i*$~$WWbZ5fyRNDionYs1;guFuC+YXws0h zxHt-~1qVMCs}3&Cx;nTDg5U>;lcSTOi<J1kq|hS9gX4a@yZ5+z2MF~N)2xm$K+`K` zDiIem*%dMHiXi&Yg&1Novy53uO2Tt|-NVP%yC~1{KKJM7QF9gpd?N7-Gt3I{I`PzI z#o)Y89A-sXB|aw}HR*!Hk6c$=e&bwlSm2pqGo6|v4ik%oHdfl06-|wJk~pGjI^_!) zmsQSNoV8MwHSft^7|Q9(OI)Wpgaj6_2niw-RIz~)Du~jmlVTx7`*9EdpyQXwrI2d_ zj2!bQLxb%2!T;cQw^n{)+)WC_fzB7({ul-VyFjC6+uz5w-8cdK&%l-5@|Wwt^e5@H zmKHezdbfd#>z1bM0hc?#z>^`HvLpFv3i&+nen#Jv1^RA*;HukOb04P<K$^Nr-T()O zz(|3z*F4_c-QL^3XPW)}0I_6pz%Yy(NdN!<24YJ`L;wH)0002_L%V+f000SaNLh0L z01m_e01m_fl`9S#00007bV*G`2jmJD1~DeqqIymM000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}00021Nkl<ZNXPAzy$J$A6ohB|0YMXUK~S)Vt3km?#15>( zHna-01d+1^v5gCiJ_9{C&+OR6WWVUK3~!b<Z&ykr{tB=JwlNJ>yx9Z2m<9k>U{u$1 zKEkP_K?9F*rOqVXfVJ&Q^%iZy^8Csrf<ehal3J1SFC-ny43Lyd>NaRJlr*WGJtWO- z-$QQ^z!~UQH6cf|v%Rog{H$q!d2ei=Vm!1An59oM5tkQ_QUz`03gQa@0000<MNUMn GLSTZsPcp~= literal 0 HcmV?d00001 diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index d9c770161..26af06559 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/"> + <file>arrow_left.png</file> <file>star.png</file> <file>swap.png</file> <file>gridpolar.png</file> From c87ca8c143ed259803a94bae803f3f4b3500fc88 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 10:34:04 +0200 Subject: [PATCH 10/27] ChannelAPI: added counter blocking features feedback --- sdrbase/channel/channelapi.cpp | 1 + sdrbase/channel/channelapi.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sdrbase/channel/channelapi.cpp b/sdrbase/channel/channelapi.cpp index 54cddb6b9..8df494a05 100644 --- a/sdrbase/channel/channelapi.cpp +++ b/sdrbase/channel/channelapi.cpp @@ -21,6 +21,7 @@ #include "channelapi.h" ChannelAPI::ChannelAPI(const QString& name, StreamType streamType) : + m_featuresSettingsFeedbackBlockCount(0), m_streamType(streamType), m_name(name), m_indexInDeviceSet(-1), diff --git a/sdrbase/channel/channelapi.h b/sdrbase/channel/channelapi.h index f0bde4a02..5d18a557e 100644 --- a/sdrbase/channel/channelapi.h +++ b/sdrbase/channel/channelapi.h @@ -122,6 +122,7 @@ public: // Features support void addFeatureSettingsFeedback(Feature *feature); void removeFeatureSettingsFeedback(Feature *feature); + void setFeatureSettingsFeedbackBlockCount(unsigned int count) { m_featuresSettingsFeedbackBlockCount = count; } // MIMO support StreamType getStreamType() const { return m_streamType; } @@ -131,6 +132,7 @@ public: protected: QList<Feature*> m_featuresSettingsFeedback; //!< list of features to report back settings changes in swagger API format + unsigned int m_featuresSettingsFeedbackBlockCount; //!< actually send feedback if 0. Decremented at each potential feedback private: StreamType m_streamType; From d2b50353da02b5d689283f4d8cec82f6503300d8 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 10:34:36 +0200 Subject: [PATCH 11/27] Freq Tracker: implemented channel API features feedback blocking counter --- plugins/channelrx/freqtracker/freqtracker.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/freqtracker/freqtracker.cpp b/plugins/channelrx/freqtracker/freqtracker.cpp index 0761cb3ca..40b60679b 100644 --- a/plugins/channelrx/freqtracker/freqtracker.cpp +++ b/plugins/channelrx/freqtracker/freqtracker.cpp @@ -258,8 +258,13 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force) webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); } - if (m_featuresSettingsFeedback.size() > 0) { - featuresSendSettings(reverseAPIKeys, settings, force); + if (m_featuresSettingsFeedback.size() > 0) + { + if (m_featuresSettingsFeedbackBlockCount == 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } else { + m_featuresSettingsFeedbackBlockCount--; + } } m_settings = settings; From b69ab47e90fcfd19192831f26f1da0f28cca56d3 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 10:35:07 +0200 Subject: [PATCH 12/27] AFC: UI changes and fixes --- plugins/feature/afc/afc.cpp | 22 +++ plugins/feature/afc/afc.h | 26 ++++ plugins/feature/afc/afcgui.cpp | 31 +++-- plugins/feature/afc/afcgui.h | 8 +- plugins/feature/afc/afcgui.ui | 220 ++++++++++++++++++------------ plugins/feature/afc/afcworker.cpp | 37 +++-- plugins/feature/afc/afcworker.h | 28 +++- 7 files changed, 259 insertions(+), 113 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index 21801de97..a74572c4c 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -37,6 +37,8 @@ MESSAGE_CLASS_DEFINITION(AFC::MsgConfigureAFC, Message) MESSAGE_CLASS_DEFINITION(AFC::MsgStartStop, Message) +MESSAGE_CLASS_DEFINITION(AFC::MsgDeviceTrack, Message) +MESSAGE_CLASS_DEFINITION(AFC::MsgDevicesApply, Message) const QString AFC::m_featureIdURI = "sdrangel.feature.afc"; const QString AFC::m_featureId = "AFC"; @@ -125,6 +127,26 @@ bool AFC::handleMessage(const Message& cmd) return true; } } + else if (MsgDeviceTrack::match(cmd)) + { + if (m_worker->isRunning()) + { + AFCWorker::MsgDeviceTrack *msg = AFCWorker::MsgDeviceTrack::create(); + m_worker->getInputMessageQueue()->push(msg); + } + + return true; + } + else if (MsgDevicesApply::match(cmd)) + { + if (m_worker->isRunning()) + { + AFCWorker::MsgDevicesApply *msg = AFCWorker::MsgDevicesApply::create(); + m_worker->getInputMessageQueue()->push(msg); + } + + return true; + } return false; } diff --git a/plugins/feature/afc/afc.h b/plugins/feature/afc/afc.h index 9ac4c1850..d29ba0ff8 100644 --- a/plugins/feature/afc/afc.h +++ b/plugins/feature/afc/afc.h @@ -81,6 +81,32 @@ public: { } }; + class MsgDeviceTrack : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgDeviceTrack* create() { + return new MsgDeviceTrack(); + } + protected: + MsgDeviceTrack() : + Message() + { } + }; + + class MsgDevicesApply : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgDevicesApply* create() { + return new MsgDevicesApply(); + } + protected: + MsgDevicesApply() : + Message() + { } + }; + AFC(WebAPIAdapterInterface *webAPIAdapterInterface); virtual ~AFC(); virtual void destroy() { delete this; } diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index cba3a803d..fc4f3cf7b 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -303,12 +303,6 @@ void AFCGUI::on_startStop_toggled(bool checked) } } -void AFCGUI::on_devicesRefresh_clicked() -{ - updateDeviceSetLists(); - displaySettings(); -} - void AFCGUI::on_hasTargetFrequency_toggled(bool checked) { m_settings.m_hasTargetFrequency = checked; @@ -327,6 +321,25 @@ void AFCGUI::on_transverterTarget_toggled(bool checked) applySettings(); } + +void AFCGUI::on_toleranceFrequency_changed(quint64 value) +{ + m_settings.m_freqTolerance = value; + applySettings(); +} + +void AFCGUI::on_deviceTrack_clicked() +{ + AFC::MsgDeviceTrack *msg = AFC::MsgDeviceTrack::create(); + m_afc->getInputMessageQueue()->push(msg); +} + +void AFCGUI::on_devicesRefresh_clicked() +{ + updateDeviceSetLists(); + displaySettings(); +} + void AFCGUI::on_trackerDevice_currentIndexChanged(int index) { if (index >= 0) @@ -345,11 +358,9 @@ void AFCGUI::on_trackedDevice_currentIndexChanged(int index) } } - -void AFCGUI::on_toleranceFrequency_changed(quint64 value) +void AFCGUI::on_devicesApply_clicked() { - m_settings.m_freqTolerance = value; - applySettings(); + } void AFCGUI::updateStatus() diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index 7b04f6382..83e469f8d 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -75,12 +75,14 @@ private slots: void handleInputMessages(); void on_startStop_toggled(bool checked); void on_hasTargetFrequency_toggled(bool checked); - void on_devicesRefresh_clicked(); - void on_transverterTarget_toggled(bool checked); void on_targetFrequency_changed(quint64 value); + void on_transverterTarget_toggled(bool checked); + void on_toleranceFrequency_changed(quint64 value); + void on_deviceTrack_clicked(); + void on_devicesRefresh_clicked(); void on_trackerDevice_currentIndexChanged(int index); void on_trackedDevice_currentIndexChanged(int index); - void on_toleranceFrequency_changed(quint64 value); + void on_devicesApply_clicked(); void updateStatus(); }; diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui index cef53c7ce..6bd30d584 100644 --- a/plugins/feature/afc/afcgui.ui +++ b/plugins/feature/afc/afcgui.ui @@ -137,96 +137,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="devicesLayout"> - <item> - <widget class="QPushButton" name="devicesRefresh"> - <property name="maximumSize"> - <size> - <width>24</width> - <height>16777215</height> - </size> - </property> - <property name="toolTip"> - <string>Refresh indexes of available device sets</string> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../../../sdrgui/resources/res.qrc"> - <normaloff>:/recycle.png</normaloff>:/recycle.png</iconset> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="trackerLabel"> - <property name="text"> - <string>Tracker</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="trackerDevice"> - <property name="minimumSize"> - <size> - <width>55</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>50</width> - <height>16777215</height> - </size> - </property> - <property name="toolTip"> - <string>Tracker deviceset index</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="trackedLabel"> - <property name="text"> - <string>Tracked</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="trackedDevice"> - <property name="minimumSize"> - <size> - <width>55</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>50</width> - <height>16777215</height> - </size> - </property> - <property name="toolTip"> - <string>Tracked deviceset index</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="DelaysLayout"> + <layout class="QHBoxLayout" name="toleranceLayout"> <item> <widget class="QLabel" name="toleranceLabel"> <property name="toolTip"> @@ -275,6 +186,26 @@ </property> </widget> </item> + <item> + <widget class="QPushButton" name="deviceTrack"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="toolTip"> + <string>Force device tracking update</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/arrow_left.png</normaloff>:/arrow_left.png</iconset> + </property> + </widget> + </item> <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> @@ -315,6 +246,115 @@ </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="devicesLayout"> + <item> + <widget class="QPushButton" name="devicesRefresh"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Refresh indexes of available device sets</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/recycle.png</normaloff>:/recycle.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="trackerLabel"> + <property name="text"> + <string>Tracker</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="trackerDevice"> + <property name="minimumSize"> + <size> + <width>55</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Tracker deviceset index</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="trackedLabel"> + <property name="text"> + <string>Tracked</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="trackedDevice"> + <property name="minimumSize"> + <size> + <width>55</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Tracked deviceset index</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="devicesApply"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="toolTip"> + <string>Reinitialization of device data</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/arrow_left.png</normaloff>:/arrow_left.png</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> </layout> </widget> </widget> diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index 731765e3d..cec3f59e4 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -36,6 +36,8 @@ MESSAGE_CLASS_DEFINITION(AFCWorker::MsgConfigureAFCWorker, Message) MESSAGE_CLASS_DEFINITION(AFCWorker::MsgTrackedDeviceChange, Message) +MESSAGE_CLASS_DEFINITION(AFCWorker::MsgDeviceTrack, Message) +MESSAGE_CLASS_DEFINITION(AFCWorker::MsgDevicesApply, Message) AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_webAPIAdapterInterface(webAPIAdapterInterface), @@ -101,15 +103,28 @@ bool AFCWorker::handleMessage(const Message& cmd) } else if (Feature::MsgChannelSettings::match(cmd)) { - qDebug() << "AFCWorker::handleMessage: Feature::MsgChannelSettings"; QMutexLocker mutexLocker(&m_mutex); Feature::MsgChannelSettings& cfg = (Feature::MsgChannelSettings&) cmd; SWGSDRangel::SWGChannelSettings *swgChannelSettings = cfg.getSWGSettings(); + qDebug() << "AFCWorker::handleMessage: Feature::MsgChannelSettings:" << *swgChannelSettings->getChannelType(); processChannelSettings(cfg.getChannelAPI(), cfg.getChannelSettingsKeys(), swgChannelSettings); delete swgChannelSettings; return true; } + else if (MsgDeviceTrack::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + updateTarget(); + return true; + } + else if (MsgDevicesApply::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + initTrackerDeviceSet(m_settings.m_trackerDeviceSetIndex); + initTrackedDeviceSet(m_settings.m_trackedDeviceSetIndex); + return true; + } else { return false; @@ -286,7 +301,7 @@ void AFCWorker::processChannelSettings( } } -bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset) +bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset, unsigned int blockCount) { SWGSDRangel::SWGChannelSettings swgChannelSettings; SWGSDRangel::SWGErrorResponse errorResponse; @@ -306,6 +321,7 @@ bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int o .arg(jsonSettingsStr); swgChannelSettings.fromJson(jsonStr); + channelAPI->setFeatureSettingsFeedbackBlockCount(1); int httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch( m_trackedDeviceSet->getIndex(), channelAPI->getIndexInDeviceSet(), @@ -344,20 +360,20 @@ void AFCWorker::updateTarget() } else { - qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device frequency"; + qDebug() << "AFCWorker::updateTarget: cannot find device frequency"; return; } } else { - qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); + qDebug() << "AFCWorker::updateTarget: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); return; } int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; int64_t correction = m_settings.m_targetFrequency - trackerFrequency; int64_t tolerance = m_settings.m_freqTolerance; - qDebug() << "AFCWorker::initTrackerDeviceSet: correction:" << correction << "tolerance:" << tolerance; + qDebug() << "AFCWorker::updateTarget: correction:" << correction << "tolerance:" << tolerance; if ((correction > -tolerance) && (correction < tolerance)) { return; @@ -376,12 +392,12 @@ void AFCWorker::updateTarget() } else { - qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; + qDebug() << "AFCWorker::updateTarget: cannot find device transverter frequency"; return; } // adjust tracker offset - if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction)) { + if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction, 1)) { m_trackerChannelOffset += correction; } } @@ -397,7 +413,7 @@ void AFCWorker::updateTarget() } else { - qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; + qDebug() << "AFCWorker::updateTarget: cannot find device transverter frequency"; return; } } @@ -415,6 +431,10 @@ bool AFCWorker::updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, QString jsonSettingsStr = tr("\"%1\":%2").arg(key).arg(frequency); QString deviceSettingsKey; getDeviceSettingsKey(deviceAPI, deviceSettingsKey); + qDebug() << "AFCWorker::updateDeviceFrequency:" + << deviceAPI->getHardwareId() + << ":" << key + << ":" << frequency; QString jsonStr = tr("{ \"deviceHwType\": \"%1\", \"direction\": \"%2\", \"%3\": {%4}}") .arg(deviceAPI->getHardwareId()) @@ -422,7 +442,6 @@ bool AFCWorker::updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, .arg(deviceSettingsKey) .arg(jsonSettingsStr); swgDeviceSettings.fromJson(jsonStr); - qDebug() << "AFCWorker::updateDeviceFrequency:" << jsonStr; int httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch ( diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index 38bf4df24..3035f11aa 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -78,6 +78,32 @@ public: { } }; + class MsgDeviceTrack : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgDeviceTrack* create() { + return new MsgDeviceTrack(); + } + protected: + MsgDeviceTrack() : + Message() + { } + }; + + class MsgDevicesApply : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgDevicesApply* create() { + return new MsgDevicesApply(); + } + protected: + MsgDevicesApply() : + Message() + { } + }; + AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface); ~AFCWorker(); void reset(); @@ -136,7 +162,7 @@ private: const QList<QString> &channelSettingsKeys, SWGSDRangel::SWGChannelSettings *swgChannelSettings ); - bool updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset); + bool updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset, unsigned int blockCount = 0); void updateTarget(); bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); int getDeviceDirection(DeviceAPI *deviceAPI); From bee032833e778789f338b6e77b3c669382650158 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 13:05:28 +0200 Subject: [PATCH 13/27] AFC: process tracker frequency change only if its offset actually chages --- plugins/feature/afc/afcgui.cpp | 2 +- plugins/feature/afc/afcworker.cpp | 46 +++++++++++++++++-------------- plugins/feature/afc/afcworker.h | 2 +- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index fc4f3cf7b..97523323c 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -124,7 +124,7 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur setAttribute(Qt::WA_DeleteOnClose, true); ui->targetFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); - ui->targetFrequency->setValueRange(11, 0, 99999999999L); + ui->targetFrequency->setValueRange(10, 0, 9999999999L); ui->toleranceFrequency->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); ui->toleranceFrequency->setValueRange(5, 0, 99999L); diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index cec3f59e4..0cbf59436 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -115,7 +115,7 @@ bool AFCWorker::handleMessage(const Message& cmd) else if (MsgDeviceTrack::match(cmd)) { QMutexLocker mutexLocker(&m_mutex); - updateTarget(); + updateTarget(m_trackerChannelOffset); return true; } else if (MsgDevicesApply::match(cmd)) @@ -267,24 +267,30 @@ void AFCWorker::processChannelSettings( if (*swgChannelSettings->getChannelType() == "FreqTracker") { - m_trackerChannelOffset = swgChannelSettings->getFreqTrackerSettings()->getInputFrequencyOffset(); - QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); + int trackerChannelOffset = swgChannelSettings->getFreqTrackerSettings()->getInputFrequencyOffset(); - for (; it != m_channelsMap.end(); ++it) + if (trackerChannelOffset != m_trackerChannelOffset) { - if (mainCore->existsChannel(it.key())) - { - int channelOffset = it.value().m_channelOffset + m_trackerChannelOffset - it.value().m_trackerOffset; - updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); - } - else - { - m_channelsMap.erase(it); - } - } + QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); - if (m_settings.m_hasTargetFrequency) { - updateTarget(); + for (; it != m_channelsMap.end(); ++it) + { + if (mainCore->existsChannel(it.key())) + { + int channelOffset = it.value().m_channelOffset + trackerChannelOffset - it.value().m_trackerOffset; + updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); + } + else + { + m_channelsMap.erase(it); + } + } + + if (m_settings.m_hasTargetFrequency) { + updateTarget(trackerChannelOffset); + } + + m_trackerChannelOffset = trackerChannelOffset; } } else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) @@ -340,7 +346,7 @@ bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int o return true; } -void AFCWorker::updateTarget() +void AFCWorker::updateTarget(int& trackerChannelOffset) { SWGSDRangel::SWGDeviceSettings resDevice; SWGSDRangel::SWGChannelSettings resChannel; @@ -370,7 +376,7 @@ void AFCWorker::updateTarget() return; } - int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; + int64_t trackerFrequency = m_trackerDeviceFrequency + trackerChannelOffset; int64_t correction = m_settings.m_targetFrequency - trackerFrequency; int64_t tolerance = m_settings.m_freqTolerance; qDebug() << "AFCWorker::updateTarget: correction:" << correction << "tolerance:" << tolerance; @@ -397,8 +403,8 @@ void AFCWorker::updateTarget() } // adjust tracker offset - if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction, 1)) { - m_trackerChannelOffset += correction; + if (updateChannelOffset(m_freqTracker, 0, trackerChannelOffset + correction, 1)) { + trackerChannelOffset += correction; } } else // act on device diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index 3035f11aa..5c31acf0e 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -163,7 +163,7 @@ private: SWGSDRangel::SWGChannelSettings *swgChannelSettings ); bool updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset, unsigned int blockCount = 0); - void updateTarget(); + void updateTarget(int& trackerChannelOffset); bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); int getDeviceDirection(DeviceAPI *deviceAPI); void getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey); From 86ce2ca843b80a1d0a6b03ced3c758a2a1a95c28 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sat, 24 Oct 2020 17:58:07 +0200 Subject: [PATCH 14/27] AFC: process tracker frequency change only if its offset actually chages --- .../channelrx/freqtracker/freqtrackergui.ui | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/plugins/channelrx/freqtracker/freqtrackergui.ui b/plugins/channelrx/freqtracker/freqtrackergui.ui index 6238f9883..3927ef6d2 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.ui +++ b/plugins/channelrx/freqtracker/freqtrackergui.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>360</width> - <height>145</height> + <height>327</height> </rect> </property> <property name="sizePolicy"> @@ -681,6 +681,49 @@ </item> </layout> </widget> + <widget class="QWidget" name="spectrumContainer" native="true"> + <property name="geometry"> + <rect> + <x>0</x> + <y>150</y> + <width>351</width> + <height>171</height> + </rect> + </property> + <property name="windowTitle"> + <string>Channel Spectrum</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>2</number> + </property> + <property name="leftMargin"> + <number>3</number> + </property> + <property name="topMargin"> + <number>3</number> + </property> + <property name="rightMargin"> + <number>3</number> + </property> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <widget class="GLSpectrum" name="glSpectrum" native="true"> + <property name="font"> + <font> + <family>Liberation Mono</family> + <pointsize>8</pointsize> + </font> + </property> + </widget> + </item> + <item> + <widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/> + </item> + </layout> + </widget> </widget> <customwidgets> <customwidget> @@ -689,23 +732,35 @@ <header>gui/rollupwidget.h</header> <container>1</container> </customwidget> + <customwidget> + <class>ButtonSwitch</class> + <extends>QToolButton</extends> + <header>gui/buttonswitch.h</header> + </customwidget> <customwidget> <class>LevelMeterSignalDB</class> <extends>QWidget</extends> <header>gui/levelmeter.h</header> <container>1</container> </customwidget> - <customwidget> - <class>ButtonSwitch</class> - <extends>QToolButton</extends> - <header>gui/buttonswitch.h</header> - </customwidget> <customwidget> <class>ValueDialZ</class> <extends>QWidget</extends> <header>gui/valuedialz.h</header> <container>1</container> </customwidget> + <customwidget> + <class>GLSpectrum</class> + <extends>QWidget</extends> + <header>gui/glspectrum.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>GLSpectrumGUI</class> + <extends>QWidget</extends> + <header>gui/glspectrumgui.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources> <include location="../../../sdrgui/resources/res.qrc"/> From b04bb24146dd5eea5563ba52948f8cdf287190cb Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sun, 25 Oct 2020 00:46:49 +0200 Subject: [PATCH 15/27] Frequency Tracker: add spectrum display. Implements #665 --- doc/img/FreqTracker_plugin.png | Bin 24269 -> 57921 bytes doc/img/FreqTracker_plugin.xcf | Bin 85946 -> 364595 bytes plugins/channelrx/freqtracker/freqtracker.cpp | 2 ++ plugins/channelrx/freqtracker/freqtracker.h | 3 +++ .../freqtracker/freqtrackerbaseband.h | 3 +++ .../channelrx/freqtracker/freqtrackergui.cpp | 21 ++++++++++++++++++ .../channelrx/freqtracker/freqtrackergui.h | 4 +++- .../channelrx/freqtracker/freqtrackergui.ui | 14 ++++-------- .../freqtracker/freqtrackersettings.cpp | 15 +++++++++++-- .../freqtracker/freqtrackersettings.h | 2 ++ .../channelrx/freqtracker/freqtrackersink.cpp | 18 +++++++++++++++ .../channelrx/freqtracker/freqtrackersink.h | 9 +++++++- plugins/channelrx/freqtracker/readme.md | 6 ++++- 13 files changed, 82 insertions(+), 15 deletions(-) diff --git a/doc/img/FreqTracker_plugin.png b/doc/img/FreqTracker_plugin.png index a3304a78acc9bb434ae0fccdf677ebe19d6ecf6f..8ea6cbbee6aaceca688c4e98d6106f8eb9d82e99 100644 GIT binary patch literal 57921 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%0Ak0>9qFzvmCnWGH)SM-=B+C^@~_yezm#i@ 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 literal 24269 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 diff --git a/doc/img/FreqTracker_plugin.xcf b/doc/img/FreqTracker_plugin.xcf index b84be5bfe984cecbec22fd255de747d0b23f5849..c542504eed07d01fc1ef074f6b6cec65c40db411 100644 GIT binary patch literal 364595 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�@>wxWqOoYww#FfBFLMGu~YnTMv;VG!Y6xbL{ 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 Bkr@C0 literal 85946 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 OSCMDk4zc#GJmP;W(q2md diff --git a/plugins/channelrx/freqtracker/freqtracker.cpp b/plugins/channelrx/freqtracker/freqtracker.cpp index 40b60679b..73e66fb6c 100644 --- a/plugins/channelrx/freqtracker/freqtracker.cpp +++ b/plugins/channelrx/freqtracker/freqtracker.cpp @@ -55,12 +55,14 @@ const int FreqTracker::m_udpBlockSize = 512; FreqTracker::FreqTracker(DeviceAPI *deviceAPI) : ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), m_deviceAPI(deviceAPI), + m_spectrumVis(SDR_RX_SCALEF), m_basebandSampleRate(0) { setObjectName(m_channelId); m_thread = new QThread(this); m_basebandSink = new FreqTrackerBaseband(); + m_basebandSink->setSpectrumSink(&m_spectrumVis); propagateMessageQueue(getInputMessageQueue()); m_basebandSink->moveToThread(m_thread); diff --git a/plugins/channelrx/freqtracker/freqtracker.h b/plugins/channelrx/freqtracker/freqtracker.h index e820ec619..c374384ae 100644 --- a/plugins/channelrx/freqtracker/freqtracker.h +++ b/plugins/channelrx/freqtracker/freqtracker.h @@ -24,6 +24,7 @@ #include <QMutex> #include "dsp/basebandsamplesink.h" +#include "dsp/spectrumvis.h" #include "channel/channelapi.h" #include "util/message.h" @@ -109,6 +110,7 @@ public: const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response); + SpectrumVis *getSpectrumVis() { return &m_spectrumVis; } uint32_t getSampleRate() const { return m_basebandSink->getSampleRate(); } double getMagSq() const { return m_basebandSink->getMagSq(); } bool getSquelchOpen() const { return m_basebandSink->getSquelchOpen(); } @@ -131,6 +133,7 @@ private: QThread *m_thread; FreqTrackerBaseband* m_basebandSink; FreqTrackerSettings m_settings; + SpectrumVis m_spectrumVis; int m_basebandSampleRate; //!< stored from device message used when starting baseband sink static const int m_udpBlockSize; QNetworkAccessManager *m_networkManager; diff --git a/plugins/channelrx/freqtracker/freqtrackerbaseband.h b/plugins/channelrx/freqtracker/freqtrackerbaseband.h index ae3ac94ea..716b9ac7a 100644 --- a/plugins/channelrx/freqtracker/freqtrackerbaseband.h +++ b/plugins/channelrx/freqtracker/freqtrackerbaseband.h @@ -28,6 +28,7 @@ #include "freqtrackersink.h" class DownChannelizer; +class SpectrumVis; class FreqTrackerBaseband : public QObject { @@ -61,6 +62,7 @@ public: void reset(); void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication + void setSpectrumSink(SpectrumVis* spectrumSink) { m_spectrumVis = spectrumSink; m_sink.setSpectrumSink(spectrumSink); } int getChannelSampleRate() const; void setBasebandSampleRate(int sampleRate); void setMessageQueueToInput(MessageQueue *messageQueue) { m_sink.setMessageQueueToInput(messageQueue); } @@ -80,6 +82,7 @@ private: MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication FreqTrackerSettings m_settings; unsigned int m_basebandSampleRate; + SpectrumVis *m_spectrumVis; QMutex m_mutex; bool handleMessage(const Message& cmd); diff --git a/plugins/channelrx/freqtracker/freqtrackergui.cpp b/plugins/channelrx/freqtracker/freqtrackergui.cpp index 91d143a5e..b876a872e 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.cpp +++ b/plugins/channelrx/freqtracker/freqtrackergui.cpp @@ -91,6 +91,8 @@ bool FreqTrackerGUI::handleMessage(const Message& message) m_basebandSampleRate = cfg.getSampleRate(); int sinkSampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim); ui->channelSampleRateText->setText(tr("%1k").arg(QString::number(sinkSampleRate / 1000.0f, 'g', 5))); + ui->glSpectrum->setSampleRate(sinkSampleRate); + m_pllChannelMarker.setBandwidth(sinkSampleRate/1000); if (sinkSampleRate > 1000) { ui->rfBW->setMaximum(sinkSampleRate/100); @@ -151,6 +153,8 @@ void FreqTrackerGUI::on_log2Decim_currentIndexChanged(int index) m_settings.m_log2Decim = index < 0 ? 0 : index > 6 ? 6 : index; int sinkSampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim); ui->channelSampleRateText->setText(tr("%1k").arg(QString::number(sinkSampleRate / 1000.0f, 'g', 5))); + ui->glSpectrum->setSampleRate(sinkSampleRate); + m_pllChannelMarker.setBandwidth(sinkSampleRate/1000); if (sinkSampleRate > 1000) { ui->rfBW->setMaximum(sinkSampleRate/100); @@ -288,6 +292,7 @@ FreqTrackerGUI::FreqTrackerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B m_pluginAPI(pluginAPI), m_deviceUISet(deviceUISet), m_channelMarker(this), + m_pllChannelMarker(this), m_basebandSampleRate(0), m_doApplySettings(true), m_squelchOpen(false), @@ -300,6 +305,8 @@ FreqTrackerGUI::FreqTrackerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B m_freqTracker = reinterpret_cast<FreqTracker*>(rxChannel); m_freqTracker->setMessageQueueToGUI(getInputMessageQueue()); + m_spectrumVis = m_freqTracker->getSpectrumVis(); + m_spectrumVis->setGLSpectrum(ui->glSpectrum); connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms @@ -318,10 +325,23 @@ FreqTrackerGUI::FreqTrackerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B setTitleColor(m_channelMarker.getColor()); m_settings.setChannelMarker(&m_channelMarker); + m_settings.setSpectrumGUI(ui->spectrumGUI); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); + ui->glSpectrum->setCenterFrequency(0); + m_pllChannelMarker.blockSignals(true); + m_pllChannelMarker.setColor(Qt::gray); + m_pllChannelMarker.setCenterFrequency(0); + m_pllChannelMarker.setBandwidth(35); + m_pllChannelMarker.setTitle("Tracker"); + m_pllChannelMarker.setMovable(false); + m_pllChannelMarker.blockSignals(false); + m_pllChannelMarker.setVisible(true); + ui->glSpectrum->addChannelMarker(&m_pllChannelMarker); + ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum); + connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor())); connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor())); connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); @@ -445,6 +465,7 @@ void FreqTrackerGUI::tick() int freq = m_freqTracker->getAvgDeltaFreq(); QLocale loc; ui->trackingFrequencyText->setText(tr("%1 Hz").arg(loc.toString(freq))); + m_pllChannelMarker.setCenterFrequency(freq); if (m_settings.m_tracking) { ui->tracking->setToolTip("Tracking on"); diff --git a/plugins/channelrx/freqtracker/freqtrackergui.h b/plugins/channelrx/freqtracker/freqtrackergui.h index a0fa5b636..6e9b6e78f 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.h +++ b/plugins/channelrx/freqtracker/freqtrackergui.h @@ -28,9 +28,9 @@ class PluginAPI; class DeviceUISet; - class FreqTracker; class BasebandSampleSink; +class SpectrumVis; namespace Ui { class FreqTrackerGUI; @@ -57,11 +57,13 @@ private: PluginAPI* m_pluginAPI; DeviceUISet* m_deviceUISet; ChannelMarker m_channelMarker; + ChannelMarker m_pllChannelMarker; FreqTrackerSettings m_settings; int m_basebandSampleRate; bool m_doApplySettings; FreqTracker* m_freqTracker; + SpectrumVis* m_spectrumVis; bool m_squelchOpen; uint32_t m_tickCount; MessageQueue m_inputMessageQueue; diff --git a/plugins/channelrx/freqtracker/freqtrackergui.ui b/plugins/channelrx/freqtracker/freqtrackergui.ui index 3927ef6d2..1419b08ed 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.ui +++ b/plugins/channelrx/freqtracker/freqtrackergui.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>360</width> + <width>400</width> <height>327</height> </rect> </property> @@ -18,16 +18,10 @@ </property> <property name="minimumSize"> <size> - <width>360</width> + <width>400</width> <height>100</height> </size> </property> - <property name="maximumSize"> - <size> - <width>360</width> - <height>16777215</height> - </size> - </property> <property name="font"> <font> <family>Liberation Sans</family> @@ -45,7 +39,7 @@ <rect> <x>0</x> <y>0</y> - <width>358</width> + <width>401</width> <height>140</height> </rect> </property> @@ -686,7 +680,7 @@ <rect> <x>0</x> <y>150</y> - <width>351</width> + <width>391</width> <height>171</height> </rect> </property> diff --git a/plugins/channelrx/freqtracker/freqtrackersettings.cpp b/plugins/channelrx/freqtracker/freqtrackersettings.cpp index 65f2c4f53..bf187540d 100644 --- a/plugins/channelrx/freqtracker/freqtrackersettings.cpp +++ b/plugins/channelrx/freqtracker/freqtrackersettings.cpp @@ -23,7 +23,8 @@ #include "freqtrackersettings.h" FreqTrackerSettings::FreqTrackerSettings() : - m_channelMarker(0) + m_channelMarker(0), + m_spectrumGUI(0) { resetToDefaults(); } @@ -57,6 +58,10 @@ QByteArray FreqTrackerSettings::serialize() const s.writeS32(1, m_inputFrequencyOffset); s.writeS32(2, m_rfBandwidth/100); s.writeU32(3, m_log2Decim); + + if (m_spectrumGUI) { + s.writeBlob(4, m_spectrumGUI->serialize()); + } s.writeS32(5, m_squelch); if (m_channelMarker) { @@ -105,7 +110,13 @@ bool FreqTrackerSettings::deserialize(const QByteArray& data) m_rfBandwidth = 100 * tmp; d.readU32(3, &utmp, 0); m_log2Decim = utmp > 6 ? 6 : utmp; - d.readS32(4, &tmp, 20); + + if (m_spectrumGUI) + { + d.readBlob(4, &bytetmp); + m_spectrumGUI->deserialize(bytetmp); + } + d.readS32(5, &tmp, -40); m_squelch = tmp; d.readBlob(6, &bytetmp); diff --git a/plugins/channelrx/freqtracker/freqtrackersettings.h b/plugins/channelrx/freqtracker/freqtrackersettings.h index aabd85f7e..71e287f1e 100644 --- a/plugins/channelrx/freqtracker/freqtrackersettings.h +++ b/plugins/channelrx/freqtracker/freqtrackersettings.h @@ -41,6 +41,7 @@ struct FreqTrackerSettings quint32 m_rgbColor; QString m_title; Serializable *m_channelMarker; + Serializable *m_spectrumGUI; float m_alphaEMA; //!< alpha factor for delta frequency EMA bool m_tracking; TrackerType m_trackerType; @@ -58,6 +59,7 @@ struct FreqTrackerSettings FreqTrackerSettings(); void resetToDefaults(); void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; } QByteArray serialize() const; bool deserialize(const QByteArray& data); }; diff --git a/plugins/channelrx/freqtracker/freqtrackersink.cpp b/plugins/channelrx/freqtracker/freqtrackersink.cpp index 390ae77ce..4cbb8e85b 100644 --- a/plugins/channelrx/freqtracker/freqtrackersink.cpp +++ b/plugins/channelrx/freqtracker/freqtrackersink.cpp @@ -22,6 +22,7 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "dsp/fftfilt.h" +#include "dsp/spectrumvis.h" #include "util/db.h" #include "util/stepfunctions.h" #include "util/messagequeue.h" @@ -33,6 +34,8 @@ FreqTrackerSink::FreqTrackerSink() : m_channelSampleRate(48000), m_inputFrequencyOffset(0), m_sinkSampleRate(48000), + m_spectrumSink(nullptr), + m_sampleBufferCount(0), m_squelchOpen(false), m_squelchGate(0), m_magsqSum(0.0f), @@ -52,6 +55,8 @@ FreqTrackerSink::FreqTrackerSink() : m_timer = &DSPEngine::instance()->getMasterTimer(); #endif m_magsq = 0.0; + m_sampleBufferSize = m_sinkSampleRate / 20; // 50 ms + m_sampleBuffer.resize(m_sampleBufferSize); m_rrcFilter = new fftfilt(m_settings.m_rfBandwidth / m_sinkSampleRate, 2*1024); m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain @@ -102,6 +107,7 @@ void FreqTrackerSink::processOneSample(Complex &ci) { fftfilt::cmplx *sideband; int n_out; + m_sampleBuffer[m_sampleBufferCount++] = Sample(ci.real(), ci.imag()); if (m_settings.m_rrc) { @@ -168,7 +174,15 @@ void FreqTrackerSink::processOneSample(Complex &ci) m_pll.feed(re, im); } } + } + + if (m_spectrumSink && (m_sampleBufferCount == m_sampleBufferSize)) + { + m_spectrumSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), false); + m_sampleBufferCount = 0; + } + } Real FreqTrackerSink::getFrequency() const @@ -215,6 +229,10 @@ void FreqTrackerSink::applyChannelSettings(int sinkSampleRate, int channelSample if (useInterpolator) { setInterpolator(); } + + m_sampleBufferSize = m_sinkSampleRate / 20; // 50 ms + m_sampleBuffer.resize(m_sampleBufferSize); + m_sampleBufferCount = 0; } void FreqTrackerSink::applySettings(const FreqTrackerSettings& settings, bool force) diff --git a/plugins/channelrx/freqtracker/freqtrackersink.h b/plugins/channelrx/freqtracker/freqtrackersink.h index be732bcd4..3a9369f71 100644 --- a/plugins/channelrx/freqtracker/freqtrackersink.h +++ b/plugins/channelrx/freqtracker/freqtrackersink.h @@ -36,6 +36,7 @@ #include "freqtrackersettings.h" +class SpectrumVis; class fftfilt; class MessageQueue; class QTimer; @@ -48,6 +49,7 @@ public: virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); + void setSpectrumSink(SpectrumVis* spectrumSink) { m_spectrumSink = spectrumSink; } void applySettings(const FreqTrackerSettings& settings, bool force = false); void applyChannelSettings(int sinkSampleRate, int channelSampleRate, int channelFrequencyOffset, bool force = false); void setMessageQueueToInput(MessageQueue *messageQueue) { m_messageQueueToInput = messageQueue;} @@ -99,6 +101,11 @@ private: int m_inputFrequencyOffset; uint32_t m_sinkSampleRate; + SpectrumVis* m_spectrumSink; + SampleVector m_sampleBuffer; + unsigned int m_sampleBufferCount; + unsigned int m_sampleBufferSize; + NCOF m_nco; PhaseLockComplex m_pll; FreqLockComplex m_fll; @@ -138,4 +145,4 @@ private slots: void tick(); }; -#endif // INCLUDE_FREQTRACKERSINK_H \ No newline at end of file +#endif // INCLUDE_FREQTRACKERSINK_H diff --git a/plugins/channelrx/freqtracker/readme.md b/plugins/channelrx/freqtracker/readme.md index 4f9b6a7e6..e72ae67b9 100644 --- a/plugins/channelrx/freqtracker/readme.md +++ b/plugins/channelrx/freqtracker/readme.md @@ -98,4 +98,8 @@ This is the squelch threshold in dB. The average total power received in the sig <h4>10: Squelch time gate</h4> -Number of milliseconds following squelch gate opening after which the signal is declared open. 0 means squelch is declared open with no delay and is suitable for burst signals. The value can be varied in steps of 10 ms from 0 to 990 ms. \ No newline at end of file +Number of milliseconds following squelch gate opening after which the signal is declared open. 0 means squelch is declared open with no delay and is suitable for burst signals. The value can be varied in steps of 10 ms from 0 to 990 ms. + +<h4>11: Channel spectrum</h4> + +This is the spectrum display of the tracker channel. When the tracker is locked to the signal the center of the channel should fall almost in the middle of the signal spectrum (ideally in the middle when the tracker error is zero). Thus the locking can be followed dynamically and it can be more reliable than the lock indicator. A channel marker shows the tracker offset from the channel center frequency (tracker error). Its width is the tracker error tolerance but is hardly visible since it is 1/1000th of the channel width. Controls on the bottom of the panel are identical to the ones of the main spectrum display. From d5fa8f45c185fd4db73e584129b563ceae043fc1 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sun, 25 Oct 2020 11:32:47 +0100 Subject: [PATCH 16/27] AFC: REST API: added tracker adjustment period --- swagger/sdrangel/api/swagger/include/AFC.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swagger/sdrangel/api/swagger/include/AFC.yaml b/swagger/sdrangel/api/swagger/include/AFC.yaml index 4781ce38b..03a62f97c 100644 --- a/swagger/sdrangel/api/swagger/include/AFC.yaml +++ b/swagger/sdrangel/api/swagger/include/AFC.yaml @@ -31,6 +31,9 @@ AFCSettings: descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted type: integer format: int64 + trackerAdjustPeriod: + description: Tracker channel frequency adjustment period in seconds + type: integer useReverseAPI: description: Synchronize with reverse API (1 for yes, 0 for no) type: integer From 8462090038c3a67a5d8596fc4e8b9fc1c45d95bd Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Tue, 27 Oct 2020 06:19:13 +0100 Subject: [PATCH 17/27] AFC: REST API: added tracker adjustment period: generated code --- sdrbase/resources/webapi/doc/html2/index.html | 6 ++++- .../webapi/doc/swagger/include/AFC.yaml | 3 +++ swagger/sdrangel/code/html2/index.html | 6 ++++- .../code/qt5/client/SWGAFCSettings.cpp | 23 +++++++++++++++++++ .../sdrangel/code/qt5/client/SWGAFCSettings.h | 6 +++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 977025a24..0b2415c55 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -747,6 +747,10 @@ margin-bottom: 20px; "type" : "integer", "format" : "int64" }, + "trackerAdjustPeriod" : { + "type" : "integer", + "description" : "Tracker channel frequency adjustment period in seconds" + }, "useReverseAPI" : { "type" : "integer", "description" : "Synchronize with reverse API (1 for yes, 0 for no)" @@ -40048,7 +40052,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:01:09.347+01:00 + Generated 2020-10-27T06:18:18.403+01:00 </div> </div> </div> diff --git a/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml index 4781ce38b..03a62f97c 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml @@ -31,6 +31,9 @@ AFCSettings: descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted type: integer format: int64 + trackerAdjustPeriod: + description: Tracker channel frequency adjustment period in seconds + type: integer useReverseAPI: description: Synchronize with reverse API (1 for yes, 0 for no) type: integer diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 977025a24..0b2415c55 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -747,6 +747,10 @@ margin-bottom: 20px; "type" : "integer", "format" : "int64" }, + "trackerAdjustPeriod" : { + "type" : "integer", + "description" : "Tracker channel frequency adjustment period in seconds" + }, "useReverseAPI" : { "type" : "integer", "description" : "Synchronize with reverse API (1 for yes, 0 for no)" @@ -40048,7 +40052,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:01:09.347+01:00 + Generated 2020-10-27T06:18:18.403+01:00 </div> </div> </div> diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp index 012e3096c..9fb6546a8 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp @@ -44,6 +44,8 @@ SWGAFCSettings::SWGAFCSettings() { m_target_frequency_isSet = false; freq_tolerance = 0L; m_freq_tolerance_isSet = false; + tracker_adjust_period = 0; + m_tracker_adjust_period_isSet = false; use_reverse_api = 0; m_use_reverse_api_isSet = false; reverse_api_address = nullptr; @@ -78,6 +80,8 @@ SWGAFCSettings::init() { m_target_frequency_isSet = false; freq_tolerance = 0L; m_freq_tolerance_isSet = false; + tracker_adjust_period = 0; + m_tracker_adjust_period_isSet = false; use_reverse_api = 0; m_use_reverse_api_isSet = false; reverse_api_address = new QString(""); @@ -103,6 +107,7 @@ SWGAFCSettings::cleanup() { + if(reverse_api_address != nullptr) { delete reverse_api_address; } @@ -138,6 +143,8 @@ SWGAFCSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&freq_tolerance, pJson["freqTolerance"], "qint64", ""); + ::SWGSDRangel::setValue(&tracker_adjust_period, pJson["trackerAdjustPeriod"], "qint32", ""); + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); @@ -188,6 +195,9 @@ SWGAFCSettings::asJsonObject() { if(m_freq_tolerance_isSet){ obj->insert("freqTolerance", QJsonValue(freq_tolerance)); } + if(m_tracker_adjust_period_isSet){ + obj->insert("trackerAdjustPeriod", QJsonValue(tracker_adjust_period)); + } if(m_use_reverse_api_isSet){ obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); } @@ -287,6 +297,16 @@ SWGAFCSettings::setFreqTolerance(qint64 freq_tolerance) { this->m_freq_tolerance_isSet = true; } +qint32 +SWGAFCSettings::getTrackerAdjustPeriod() { + return tracker_adjust_period; +} +void +SWGAFCSettings::setTrackerAdjustPeriod(qint32 tracker_adjust_period) { + this->tracker_adjust_period = tracker_adjust_period; + this->m_tracker_adjust_period_isSet = true; +} + qint32 SWGAFCSettings::getUseReverseApi() { return use_reverse_api; @@ -366,6 +386,9 @@ SWGAFCSettings::isSet(){ if(m_freq_tolerance_isSet){ isObjectUpdated = true; break; } + if(m_tracker_adjust_period_isSet){ + isObjectUpdated = true; break; + } if(m_use_reverse_api_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h index fe1cf6551..a05789594 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h @@ -66,6 +66,9 @@ public: qint64 getFreqTolerance(); void setFreqTolerance(qint64 freq_tolerance); + qint32 getTrackerAdjustPeriod(); + void setTrackerAdjustPeriod(qint32 tracker_adjust_period); + qint32 getUseReverseApi(); void setUseReverseApi(qint32 use_reverse_api); @@ -109,6 +112,9 @@ private: qint64 freq_tolerance; bool m_freq_tolerance_isSet; + qint32 tracker_adjust_period; + bool m_tracker_adjust_period_isSet; + qint32 use_reverse_api; bool m_use_reverse_api_isSet; From be4f7f3178e0dd5aa8d03f9b54c7df864decaf6b Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sun, 25 Oct 2020 11:34:47 +0100 Subject: [PATCH 18/27] AFC: added tracker adjustment period and fixes --- plugins/feature/afc/afc.cpp | 11 + plugins/feature/afc/afcgui.cpp | 9 + plugins/feature/afc/afcgui.h | 1 + plugins/feature/afc/afcgui.ui | 399 ++++++++++++++++------------ plugins/feature/afc/afcsettings.cpp | 3 + plugins/feature/afc/afcsettings.h | 1 + plugins/feature/afc/afcworker.cpp | 87 +++--- plugins/feature/afc/afcworker.h | 2 +- 8 files changed, 301 insertions(+), 212 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index a74572c4c..2b9c1cf33 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -184,6 +184,7 @@ void AFC::applySettings(const AFCSettings& settings, bool force) << " m_transverterTarget: " << settings.m_transverterTarget << " m_targetFrequency: " << settings.m_targetFrequency << " m_freqTolerance: " << settings.m_freqTolerance + << " m_trackerAdjustPeriod:" << settings.m_trackerAdjustPeriod << " force: " << force; QList<QString> reverseAPIKeys; @@ -212,6 +213,9 @@ void AFC::applySettings(const AFCSettings& settings, bool force) if ((m_settings.m_freqTolerance != settings.m_freqTolerance) || force) { reverseAPIKeys.append("freqTolerance"); } + if ((m_settings.m_trackerAdjustPeriod != settings.m_trackerAdjustPeriod) || force) { + reverseAPIKeys.append("trackerAdjustPeriod"); + } if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { trackerDeviceChange(settings.m_trackerDeviceSetIndex); @@ -331,6 +335,7 @@ void AFC::webapiFormatFeatureSettings( response.getAfcSettings()->setTransverterTarget(settings.m_transverterTarget); response.getAfcSettings()->setTargetFrequency(settings.m_targetFrequency); response.getAfcSettings()->setFreqTolerance(settings.m_freqTolerance); + response.getAfcSettings()->setTrackerAdjustPeriod(settings.m_trackerAdjustPeriod); response.getAfcSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); @@ -374,6 +379,9 @@ void AFC::webapiUpdateFeatureSettings( if (featureSettingsKeys.contains("freqTolerance")) { settings.m_freqTolerance = response.getAfcSettings()->getFreqTolerance(); } + if (featureSettingsKeys.contains("trackerAdjustPeriod")) { + settings.m_trackerAdjustPeriod = response.getAfcSettings()->getTrackerAdjustPeriod(); + } if (featureSettingsKeys.contains("useReverseAPI")) { settings.m_useReverseAPI = response.getAfcSettings()->getUseReverseApi() != 0; } @@ -430,6 +438,9 @@ void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const A if (channelSettingsKeys.contains("freqTolerance") || force) { swgAFCSettings->setFreqTolerance(settings.m_freqTolerance); } + if (channelSettingsKeys.contains("trackerAdjustPeriod") || force) { + swgAFCSettings->setTrackerAdjustPeriod(settings.m_trackerAdjustPeriod); + } QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings") .arg(settings.m_reverseAPIAddress) diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index 97523323c..880989822 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -174,6 +174,8 @@ void AFCGUI::displaySettings() ui->transverterTarget->setChecked(m_settings.m_transverterTarget); ui->targetFrequency->setValue(m_settings.m_targetFrequency); ui->toleranceFrequency->setValue(m_settings.m_freqTolerance); + ui->targetPeriod->setValue(m_settings.m_trackerAdjustPeriod); + ui->targetPeriodText->setText(tr("%1").arg(m_settings.m_trackerAdjustPeriod)); blockApplySettings(false); } @@ -363,6 +365,13 @@ void AFCGUI::on_devicesApply_clicked() } +void AFCGUI::on_targetPeriod_valueChanged(int value) +{ + m_settings.m_trackerAdjustPeriod = value; + ui->targetPeriodText->setText(tr("%1").arg(m_settings.m_trackerAdjustPeriod)); + applySettings(); +} + void AFCGUI::updateStatus() { int state = m_afc->getState(); diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index 83e469f8d..d4bfa2b14 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -83,6 +83,7 @@ private slots: void on_trackerDevice_currentIndexChanged(int index); void on_trackedDevice_currentIndexChanged(int index); void on_devicesApply_clicked(); + void on_targetPeriod_valueChanged(int value); void updateStatus(); }; diff --git a/plugins/feature/afc/afcgui.ui b/plugins/feature/afc/afcgui.ui index 6bd30d584..bb6c85553 100644 --- a/plugins/feature/afc/afcgui.ui +++ b/plugins/feature/afc/afcgui.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>340</width> - <height>181</height> + <height>160</height> </rect> </property> <property name="sizePolicy"> @@ -34,9 +34,9 @@ <widget class="QWidget" name="settingsContainer" native="true"> <property name="geometry"> <rect> - <x>10</x> - <y>10</y> - <width>311</width> + <x>0</x> + <y>0</y> + <width>340</width> <height>151</height> </rect> </property> @@ -76,178 +76,6 @@ </property> </widget> </item> - <item> - <widget class="ButtonSwitch" name="hasTargetFrequency"> - <property name="toolTip"> - <string>Adjust device frequency to match tracker frequency</string> - </property> - <property name="text"> - <string>T</string> - </property> - </widget> - </item> - <item> - <widget class="ValueDial" name="targetFrequency" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>32</width> - <height>16</height> - </size> - </property> - <property name="font"> - <font> - <family>Liberation Mono</family> - <pointsize>12</pointsize> - </font> - </property> - <property name="cursor"> - <cursorShape>PointingHandCursor</cursorShape> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="toolTip"> - <string>Tracker frequency in Hz</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="targetFrequencyUnits"> - <property name="text"> - <string>Hz</string> - </property> - </widget> - </item> - <item> - <widget class="ButtonSwitch" name="transverterTarget"> - <property name="toolTip"> - <string>Use transverter frequency for tracker frequency adjustment</string> - </property> - <property name="text"> - <string>X</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="toleranceLayout"> - <item> - <widget class="QLabel" name="toleranceLabel"> - <property name="toolTip"> - <string/> - </property> - <property name="text"> - <string>Tol</string> - </property> - </widget> - </item> - <item> - <widget class="ValueDial" name="toleranceFrequency" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>32</width> - <height>16</height> - </size> - </property> - <property name="font"> - <font> - <family>Liberation Mono</family> - <pointsize>12</pointsize> - </font> - </property> - <property name="cursor"> - <cursorShape>PointingHandCursor</cursorShape> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="toolTip"> - <string>Frequency tolerance before device frequency is changed (Hz)</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="toleranceUnits"> - <property name="text"> - <string>Hz</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="deviceTrack"> - <property name="maximumSize"> - <size> - <width>24</width> - <height>24</height> - </size> - </property> - <property name="toolTip"> - <string>Force device tracking update</string> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../../../sdrgui/resources/res.qrc"> - <normaloff>:/arrow_left.png</normaloff>:/arrow_left.png</iconset> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="statusIndicator"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>16</width> - <height>16</height> - </size> - </property> - <property name="toolTip"> - <string>Idle</string> - </property> - <property name="styleSheet"> - <string notr="true">QLabel { background-color: gray; border-radius: 8px; }</string> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="devicesLayout"> <item> <widget class="QPushButton" name="devicesRefresh"> <property name="maximumSize"> @@ -355,6 +183,225 @@ </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="targetLayout"> + <item> + <widget class="ButtonSwitch" name="hasTargetFrequency"> + <property name="toolTip"> + <string>Tracker target frequency auto adjust</string> + </property> + <property name="text"> + <string>T</string> + </property> + </widget> + </item> + <item> + <widget class="ValueDial" name="targetFrequency" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>16</height> + </size> + </property> + <property name="font"> + <font> + <family>Liberation Mono</family> + <pointsize>12</pointsize> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Tracker target tracker frequency in Hz</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="targetFrequencyUnits"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + <item> + <widget class="ButtonSwitch" name="transverterTarget"> + <property name="toolTip"> + <string>Use transverter frequency for tracker target frequency adjustment</string> + </property> + <property name="text"> + <string>X</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="toleranceLayout"> + <item> + <widget class="QLabel" name="toleranceLabel"> + <property name="toolTip"> + <string/> + </property> + <property name="text"> + <string>&plusmn;</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + </widget> + </item> + <item> + <widget class="ValueDial" name="toleranceFrequency" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>16</height> + </size> + </property> + <property name="font"> + <font> + <family>Liberation Mono</family> + <pointsize>12</pointsize> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Tracker target frequency error tolerance (Hz)</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="toleranceUnits"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + <item> + <widget class="QDial" name="targetPeriod"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="toolTip"> + <string>Tracker target frequency adjustment period (seconds)</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>120</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>20</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="targetPeriodText"> + <property name="minimumSize"> + <size> + <width>24</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string>Tracker target frequency adjustment period (seconds)</string> + </property> + <property name="text"> + <string>000</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="deviceTrack"> + <property name="maximumSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="toolTip"> + <string>Force tracker target frequency adjustment</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../../sdrgui/resources/res.qrc"> + <normaloff>:/arrow_left.png</normaloff>:/arrow_left.png</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="statusIndicator"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="toolTip"> + <string>Idle</string> + </property> + <property name="styleSheet"> + <string notr="true">QLabel { background-color: gray; border-radius: 8px; }</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> </widget> diff --git a/plugins/feature/afc/afcsettings.cpp b/plugins/feature/afc/afcsettings.cpp index 4ca1bf8c4..0b4b1fa7c 100644 --- a/plugins/feature/afc/afcsettings.cpp +++ b/plugins/feature/afc/afcsettings.cpp @@ -37,6 +37,7 @@ void AFCSettings::resetToDefaults() m_transverterTarget = false; m_targetFrequency = 0; m_freqTolerance = 1000; + m_trackerAdjustPeriod = 20; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; m_reverseAPIPort = 8888; @@ -51,6 +52,7 @@ QByteArray AFCSettings::serialize() const s.writeString(1, m_title); s.writeU32(2, m_rgbColor); s.writeS32(3, m_trackerDeviceSetIndex); + s.writeU32(4, m_trackerAdjustPeriod); s.writeS32(5, m_trackedDeviceSetIndex); s.writeBool(6, m_hasTargetFrequency); s.writeBool(7, m_transverterTarget); @@ -85,6 +87,7 @@ bool AFCSettings::deserialize(const QByteArray& data) d.readString(1, &m_title, "AFC"); d.readU32(2, &m_rgbColor, QColor(255, 255, 0).rgb()); d.readS32(3, &m_trackerDeviceSetIndex, -1); + d.readU32(4, &m_trackerAdjustPeriod, 20); d.readS32(5, &m_trackedDeviceSetIndex, -1); d.readBool(6, &m_hasTargetFrequency, false); d.readBool(7, &m_transverterTarget, false); diff --git a/plugins/feature/afc/afcsettings.h b/plugins/feature/afc/afcsettings.h index e633e612f..a60022a64 100644 --- a/plugins/feature/afc/afcsettings.h +++ b/plugins/feature/afc/afcsettings.h @@ -33,6 +33,7 @@ struct AFCSettings bool m_transverterTarget; quint64 m_targetFrequency; quint64 m_freqTolerance; + unsigned int m_trackerAdjustPeriod; //!< tracker channel frequency adjustment period in seconds bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort; diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index 0cbf59436..7ac54626f 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -49,6 +49,11 @@ AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_mutex(QMutex::Recursive) { qDebug("AFCWorker::AFCWorker"); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTarget())); + + if (m_settings.m_hasTargetFrequency) { + m_updateTimer.start(m_settings.m_trackerAdjustPeriod * 1000); + } } AFCWorker::~AFCWorker() @@ -115,7 +120,7 @@ bool AFCWorker::handleMessage(const Message& cmd) else if (MsgDeviceTrack::match(cmd)) { QMutexLocker mutexLocker(&m_mutex); - updateTarget(m_trackerChannelOffset); + updateTarget(); return true; } else if (MsgDevicesApply::match(cmd)) @@ -152,6 +157,19 @@ void AFCWorker::applySettings(const AFCSettings& settings, bool force) initTrackedDeviceSet(settings.m_trackedDeviceSetIndex); } + if ((settings.m_trackerAdjustPeriod != m_settings.m_trackerAdjustPeriod) || force) { + m_updateTimer.setInterval(settings.m_trackerAdjustPeriod * 1000); + } + + if ((settings.m_hasTargetFrequency != m_settings.m_hasTargetFrequency) || force) + { + if (settings.m_hasTargetFrequency) { + m_updateTimer.start(m_settings.m_trackerAdjustPeriod * 1000); + } else { + m_updateTimer.stop(); + } + } + m_settings = settings; } @@ -264,45 +282,44 @@ void AFCWorker::processChannelSettings( SWGSDRangel::SWGChannelSettings *swgChannelSettings) { MainCore *mainCore = MainCore::instance(); + QJsonObject *jsonObj = swgChannelSettings->asJsonObject(); + QJsonValue channelOffsetValue; - if (*swgChannelSettings->getChannelType() == "FreqTracker") + if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) { - int trackerChannelOffset = swgChannelSettings->getFreqTrackerSettings()->getInputFrequencyOffset(); + int channelOffset = channelOffsetValue.toInt(); - if (trackerChannelOffset != m_trackerChannelOffset) + if (*swgChannelSettings->getChannelType() == "FreqTracker") { - QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); - - for (; it != m_channelsMap.end(); ++it) + if (channelOffset != m_trackerChannelOffset) { - if (mainCore->existsChannel(it.key())) - { - int channelOffset = it.value().m_channelOffset + trackerChannelOffset - it.value().m_trackerOffset; - updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); - } - else - { - m_channelsMap.erase(it); - } - } + qDebug("AFCWorker::processChannelSettings: FreqTracker offset change: %d", channelOffset); + QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); - if (m_settings.m_hasTargetFrequency) { - updateTarget(trackerChannelOffset); - } + for (; it != m_channelsMap.end(); ++it) + { + if (mainCore->existsChannel(it.key())) + { + int channelOffset = it.value().m_channelOffset + channelOffset - it.value().m_trackerOffset; + updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); + } + else + { + m_channelsMap.erase(it); + } + } - m_trackerChannelOffset = trackerChannelOffset; + m_trackerChannelOffset = channelOffset; + } } - } - else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) - { - QJsonObject *jsonObj = swgChannelSettings->asJsonObject(); - QJsonValue channelOffsetValue; - - if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) + else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) { - int channelOffset = channelOffsetValue.toInt(); - m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; - m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; + if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) + { + int channelOffset = channelOffsetValue.toInt(); + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; + } } } } @@ -346,7 +363,7 @@ bool AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int o return true; } -void AFCWorker::updateTarget(int& trackerChannelOffset) +void AFCWorker::updateTarget() { SWGSDRangel::SWGDeviceSettings resDevice; SWGSDRangel::SWGChannelSettings resChannel; @@ -376,7 +393,7 @@ void AFCWorker::updateTarget(int& trackerChannelOffset) return; } - int64_t trackerFrequency = m_trackerDeviceFrequency + trackerChannelOffset; + int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; int64_t correction = m_settings.m_targetFrequency - trackerFrequency; int64_t tolerance = m_settings.m_freqTolerance; qDebug() << "AFCWorker::updateTarget: correction:" << correction << "tolerance:" << tolerance; @@ -403,8 +420,8 @@ void AFCWorker::updateTarget(int& trackerChannelOffset) } // adjust tracker offset - if (updateChannelOffset(m_freqTracker, 0, trackerChannelOffset + correction, 1)) { - trackerChannelOffset += correction; + if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction, 1)) { + m_trackerChannelOffset += correction; } } else // act on device diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index 5c31acf0e..d1fc10140 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -163,12 +163,12 @@ private: SWGSDRangel::SWGChannelSettings *swgChannelSettings ); bool updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset, unsigned int blockCount = 0); - void updateTarget(int& trackerChannelOffset); bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); int getDeviceDirection(DeviceAPI *deviceAPI); void getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey); private slots: + void updateTarget(); void handleInputMessages(); }; From 30153a54b75457ff0f4ee7f7bf16e41a11e5b3ac Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sun, 25 Oct 2020 21:10:37 +0100 Subject: [PATCH 19/27] Frequency Tracker: REST API: added spectrum span log2 control --- swagger/sdrangel/api/swagger/include/FreqTracker.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swagger/sdrangel/api/swagger/include/FreqTracker.yaml b/swagger/sdrangel/api/swagger/include/FreqTracker.yaml index 68a029cd5..5d507b162 100644 --- a/swagger/sdrangel/api/swagger/include/FreqTracker.yaml +++ b/swagger/sdrangel/api/swagger/include/FreqTracker.yaml @@ -19,6 +19,8 @@ FreqTrackerSettings: type: integer title: type: string + spanLog2: + type: integer alphaEMA: description: Alpha factor for delta frequency EMA type: number From 23cebe596f650934897c91fab51e35664da9207e Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Tue, 27 Oct 2020 06:29:24 +0100 Subject: [PATCH 20/27] Frequency Tracker: REST API: added spectrum span log2 control: generated code --- sdrbase/resources/webapi/doc/html2/index.html | 5 +++- .../doc/swagger/include/FreqTracker.yaml | 2 ++ swagger/sdrangel/code/html2/index.html | 5 +++- .../qt5/client/SWGFreqTrackerSettings.cpp | 23 +++++++++++++++++++ .../code/qt5/client/SWGFreqTrackerSettings.h | 6 +++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 0b2415c55..e643b84ad 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -3871,6 +3871,9 @@ margin-bottom: 20px; "title" : { "type" : "string" }, + "spanLog2" : { + "type" : "integer" + }, "alphaEMA" : { "type" : "number", "format" : "float", @@ -40052,7 +40055,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:18:18.403+01:00 + Generated 2020-10-27T06:29:00.746+01:00 </div> </div> </div> diff --git a/sdrbase/resources/webapi/doc/swagger/include/FreqTracker.yaml b/sdrbase/resources/webapi/doc/swagger/include/FreqTracker.yaml index 68a029cd5..5d507b162 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FreqTracker.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FreqTracker.yaml @@ -19,6 +19,8 @@ FreqTrackerSettings: type: integer title: type: string + spanLog2: + type: integer alphaEMA: description: Alpha factor for delta frequency EMA type: number diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 0b2415c55..e643b84ad 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -3871,6 +3871,9 @@ margin-bottom: 20px; "title" : { "type" : "string" }, + "spanLog2" : { + "type" : "integer" + }, "alphaEMA" : { "type" : "number", "format" : "float", @@ -40052,7 +40055,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:18:18.403+01:00 + Generated 2020-10-27T06:29:00.746+01:00 </div> </div> </div> diff --git a/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.cpp index 1b4304d41..ecac0e393 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.cpp @@ -40,6 +40,8 @@ SWGFreqTrackerSettings::SWGFreqTrackerSettings() { m_rgb_color_isSet = false; title = nullptr; m_title_isSet = false; + span_log2 = 0; + m_span_log2_isSet = false; alpha_ema = 0.0f; m_alpha_ema_isSet = false; tracking = 0; @@ -86,6 +88,8 @@ SWGFreqTrackerSettings::init() { m_rgb_color_isSet = false; title = new QString(""); m_title_isSet = false; + span_log2 = 0; + m_span_log2_isSet = false; alpha_ema = 0.0f; m_alpha_ema_isSet = false; tracking = 0; @@ -133,6 +137,7 @@ SWGFreqTrackerSettings::cleanup() { + if(reverse_api_address != nullptr) { delete reverse_api_address; } @@ -164,6 +169,8 @@ SWGFreqTrackerSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + ::SWGSDRangel::setValue(&span_log2, pJson["spanLog2"], "qint32", ""); + ::SWGSDRangel::setValue(&alpha_ema, pJson["alphaEMA"], "float", ""); ::SWGSDRangel::setValue(&tracking, pJson["tracking"], "qint32", ""); @@ -224,6 +231,9 @@ SWGFreqTrackerSettings::asJsonObject() { if(title != nullptr && *title != QString("")){ toJsonValue(QString("title"), title, obj, QString("QString")); } + if(m_span_log2_isSet){ + obj->insert("spanLog2", QJsonValue(span_log2)); + } if(m_alpha_ema_isSet){ obj->insert("alphaEMA", QJsonValue(alpha_ema)); } @@ -327,6 +337,16 @@ SWGFreqTrackerSettings::setTitle(QString* title) { this->m_title_isSet = true; } +qint32 +SWGFreqTrackerSettings::getSpanLog2() { + return span_log2; +} +void +SWGFreqTrackerSettings::setSpanLog2(qint32 span_log2) { + this->span_log2 = span_log2; + this->m_span_log2_isSet = true; +} + float SWGFreqTrackerSettings::getAlphaEma() { return alpha_ema; @@ -480,6 +500,9 @@ SWGFreqTrackerSettings::isSet(){ if(title && *title != QString("")){ isObjectUpdated = true; break; } + if(m_span_log2_isSet){ + isObjectUpdated = true; break; + } if(m_alpha_ema_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.h b/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.h index a6855ff80..fee0e0247 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGFreqTrackerSettings.h @@ -60,6 +60,9 @@ public: QString* getTitle(); void setTitle(QString* title); + qint32 getSpanLog2(); + void setSpanLog2(qint32 span_log2); + float getAlphaEma(); void setAlphaEma(float alpha_ema); @@ -121,6 +124,9 @@ private: QString* title; bool m_title_isSet; + qint32 span_log2; + bool m_span_log2_isSet; + float alpha_ema; bool m_alpha_ema_isSet; From 573aa9b559da1e54b81fa4d5f64994dbabf6e704 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Sun, 25 Oct 2020 23:07:15 +0100 Subject: [PATCH 21/27] Frequency Tracker: added spectrum span log2 --- doc/img/FreqTracker_plugin.png | Bin 57921 -> 61210 bytes doc/img/FreqTracker_plugin.xcf | Bin 364595 -> 322034 bytes plugins/channelrx/freqtracker/freqtracker.cpp | 36 +++++++- .../channelrx/freqtracker/freqtrackergui.cpp | 46 ++++++++-- .../channelrx/freqtracker/freqtrackergui.h | 3 + .../channelrx/freqtracker/freqtrackergui.ui | 81 +++++++++++++++++- .../freqtracker/freqtrackersettings.cpp | 3 + .../freqtracker/freqtrackersettings.h | 1 + .../channelrx/freqtracker/freqtrackersink.cpp | 26 +++++- .../channelrx/freqtracker/freqtrackersink.h | 2 + plugins/channelrx/freqtracker/readme.md | 10 ++- 11 files changed, 191 insertions(+), 17 deletions(-) diff --git a/doc/img/FreqTracker_plugin.png b/doc/img/FreqTracker_plugin.png index 8ea6cbbee6aaceca688c4e98d6106f8eb9d82e99..cabc97428d39870e2baf5c19ee134449d0a2f20c 100644 GIT binary patch literal 61210 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 literal 57921 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%0Ak0>9qFzvmCnWGH)SM-=B+C^@~_yezm#i@ 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 diff --git a/doc/img/FreqTracker_plugin.xcf b/doc/img/FreqTracker_plugin.xcf index c542504eed07d01fc1ef074f6b6cec65c40db411..0c1217585a2eaa1ad7d596ff4bd0f24d5ae38755 100644 GIT binary patch delta 79915 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%0AgS@S)$IX`E$i;+(+! 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 D=*H+p delta 112980 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 diff --git a/plugins/channelrx/freqtracker/freqtracker.cpp b/plugins/channelrx/freqtracker/freqtracker.cpp index 73e66fb6c..1b5f1ff75 100644 --- a/plugins/channelrx/freqtracker/freqtracker.cpp +++ b/plugins/channelrx/freqtracker/freqtracker.cpp @@ -182,6 +182,7 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force) << " m_rrc: " << settings.m_rrc << " m_rrcRolloff: " << settings.m_rrcRolloff << " m_streamIndex: " << settings.m_streamIndex + << " m_spanLog2: " << settings.m_spanLog2 << " m_useReverseAPI: " << settings.m_useReverseAPI << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress << " m_reverseAPIPort: " << settings.m_reverseAPIPort @@ -215,6 +216,9 @@ void FreqTracker::applySettings(const FreqTrackerSettings& settings, bool force) if ((m_settings.m_alphaEMA != settings.m_alphaEMA) || force) { reverseAPIKeys.append("alphaEMA"); } + if ((m_settings.m_spanLog2 != settings.m_spanLog2) || force) { + reverseAPIKeys.append("spanLog2"); + } if ((m_settings.m_tracking != settings.m_tracking) || force) { reverseAPIKeys.append("tracking"); } @@ -354,6 +358,9 @@ void FreqTracker::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("title")) { settings.m_title = *response.getFreqTrackerSettings()->getTitle(); } + if (channelSettingsKeys.contains("spanLog2")) { + settings.m_spanLog2 = response.getFreqTrackerSettings()->getSpanLog2(); + } if (channelSettingsKeys.contains("alphaEMA")) { float alphaEMA = response.getFreqTrackerSettings()->getAlphaEma(); settings.m_alphaEMA = alphaEMA < 0.01 ? 0.01 : alphaEMA > 1.0 ? 1.0 : alphaEMA; @@ -425,6 +432,7 @@ void FreqTracker::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& r response.getFreqTrackerSettings()->setTitle(new QString(settings.m_title)); } + response.getFreqTrackerSettings()->setSpanLog2(settings.m_spanLog2); response.getFreqTrackerSettings()->setAlphaEma(settings.m_alphaEMA); response.getFreqTrackerSettings()->setTracking(settings.m_tracking ? 1 : 0); response.getFreqTrackerSettings()->setTrackerType((int) settings.m_trackerType); @@ -533,18 +541,42 @@ void FreqTracker::webapiFormatChannelSettings( if (channelSettingsKeys.contains("rfBandwidth") || force) { swgFreqTrackerSettings->setRfBandwidth(settings.m_rfBandwidth); } - if (channelSettingsKeys.contains("rgbColor") || force) { - swgFreqTrackerSettings->setRgbColor(settings.m_rgbColor); + if (channelSettingsKeys.contains("log2Decim") || force) { + swgFreqTrackerSettings->setLog2Decim(settings.m_log2Decim); } if (channelSettingsKeys.contains("squelch") || force) { swgFreqTrackerSettings->setSquelch(settings.m_squelch); } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgFreqTrackerSettings->setRgbColor(settings.m_rgbColor); + } if (channelSettingsKeys.contains("title") || force) { swgFreqTrackerSettings->setTitle(new QString(settings.m_title)); } + if (channelSettingsKeys.contains("spanLog2") || force) { + swgFreqTrackerSettings->setSpanLog2(settings.m_spanLog2); + } + if (channelSettingsKeys.contains("alphaEMA") || force) { + swgFreqTrackerSettings->setAlphaEma(settings.m_alphaEMA); + } + if (channelSettingsKeys.contains("tracking") || force) { + swgFreqTrackerSettings->setTracking(settings.m_tracking ? 1 : 0); + } if (channelSettingsKeys.contains("trackerType") || force) { swgFreqTrackerSettings->setTrackerType((int) settings.m_trackerType); } + if (channelSettingsKeys.contains("pllPskOrder") || force) { + swgFreqTrackerSettings->setPllPskOrder(settings.m_pllPskOrder); + } + if (channelSettingsKeys.contains("rrc") || force) { + swgFreqTrackerSettings->setRrc(settings.m_rrc ? 1 : 0); + } + if (channelSettingsKeys.contains("rrcRolloff") || force) { + swgFreqTrackerSettings->setRrcRolloff(settings.m_rrcRolloff); + } + if (channelSettingsKeys.contains("squelchGate") || force) { + swgFreqTrackerSettings->setSquelchGate(settings.m_squelchGate); + } if (channelSettingsKeys.contains("streamIndex") || force) { swgFreqTrackerSettings->setStreamIndex(settings.m_streamIndex); } diff --git a/plugins/channelrx/freqtracker/freqtrackergui.cpp b/plugins/channelrx/freqtracker/freqtrackergui.cpp index b876a872e..8df525b23 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.cpp +++ b/plugins/channelrx/freqtracker/freqtrackergui.cpp @@ -91,8 +91,8 @@ bool FreqTrackerGUI::handleMessage(const Message& message) m_basebandSampleRate = cfg.getSampleRate(); int sinkSampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim); ui->channelSampleRateText->setText(tr("%1k").arg(QString::number(sinkSampleRate / 1000.0f, 'g', 5))); - ui->glSpectrum->setSampleRate(sinkSampleRate); - m_pllChannelMarker.setBandwidth(sinkSampleRate/1000); + displaySpectrumBandwidth(m_settings.m_spanLog2); + m_pllChannelMarker.setBandwidth(sinkSampleRate/500); if (sinkSampleRate > 1000) { ui->rfBW->setMaximum(sinkSampleRate/100); @@ -153,8 +153,8 @@ void FreqTrackerGUI::on_log2Decim_currentIndexChanged(int index) m_settings.m_log2Decim = index < 0 ? 0 : index > 6 ? 6 : index; int sinkSampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim); ui->channelSampleRateText->setText(tr("%1k").arg(QString::number(sinkSampleRate / 1000.0f, 'g', 5))); - ui->glSpectrum->setSampleRate(sinkSampleRate); - m_pllChannelMarker.setBandwidth(sinkSampleRate/1000); + displaySpectrumBandwidth(m_settings.m_spanLog2); + m_pllChannelMarker.setBandwidth(sinkSampleRate/500); if (sinkSampleRate > 1000) { ui->rfBW->setMaximum(sinkSampleRate/100); @@ -235,6 +235,15 @@ void FreqTrackerGUI::on_squelchGate_valueChanged(int value) applySettings(); } +void FreqTrackerGUI::on_spanLog2_valueChanged(int value) +{ + if ((value < 0) || (value > 6)) { + return; + } + + applySpectrumBandwidth(ui->spanLog2->value()); +} + void FreqTrackerGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; @@ -332,9 +341,9 @@ FreqTrackerGUI::FreqTrackerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B ui->glSpectrum->setCenterFrequency(0); m_pllChannelMarker.blockSignals(true); - m_pllChannelMarker.setColor(Qt::gray); + m_pllChannelMarker.setColor(Qt::white); m_pllChannelMarker.setCenterFrequency(0); - m_pllChannelMarker.setBandwidth(35); + m_pllChannelMarker.setBandwidth(70); m_pllChannelMarker.setTitle("Tracker"); m_pllChannelMarker.setMovable(false); m_pllChannelMarker.blockSignals(false); @@ -369,6 +378,13 @@ void FreqTrackerGUI::applySettings(bool force) } } +void FreqTrackerGUI::applySpectrumBandwidth(int spanLog2, bool force) +{ + displaySpectrumBandwidth(spanLog2); + m_settings.m_spanLog2 = spanLog2; + applySettings(force); +} + void FreqTrackerGUI::displaySettings() { m_channelMarker.blockSignals(true); @@ -407,11 +423,29 @@ void FreqTrackerGUI::displaySettings() ui->squelchGateText->setText(QString("%1").arg(m_settings.m_squelchGate * 10.0f, 0, 'f', 0)); ui->squelchGate->setValue(m_settings.m_squelchGate); + displaySpectrumBandwidth(m_settings.m_spanLog2); displayStreamIndex(); blockApplySettings(false); } +void FreqTrackerGUI::displaySpectrumBandwidth(int spanLog2) +{ + int spectrumRate = (m_basebandSampleRate / (1<<m_settings.m_log2Decim)) / (1<<spanLog2); + + qDebug() << "FreqTrackerGUI::displaySpectrumBandwidth:" + << " spanLog2: " << spanLog2 + << " spectrumRate: " << spectrumRate; + + QString spanStr = QString::number(spectrumRate/1000.0, 'f', 1); + + ui->spanLog2->blockSignals(true); + ui->spanLog2->setValue(spanLog2); + ui->spanLog2->blockSignals(false); + ui->spanText->setText(tr("%1k").arg(spanStr)); + ui->glSpectrum->setSampleRate(spectrumRate); +} + void FreqTrackerGUI::displayStreamIndex() { if (m_deviceUISet->m_deviceMIMOEngine) { diff --git a/plugins/channelrx/freqtracker/freqtrackergui.h b/plugins/channelrx/freqtracker/freqtrackergui.h index 6e9b6e78f..4c7943bef 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.h +++ b/plugins/channelrx/freqtracker/freqtrackergui.h @@ -73,7 +73,9 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); + void applySpectrumBandwidth(int spanLog2, bool force = false); void displaySettings(); + void displaySpectrumBandwidth(int spanLog2); void displayStreamIndex(); bool handleMessage(const Message& message); @@ -92,6 +94,7 @@ private slots: void on_rrcRolloff_valueChanged(int value); void on_squelch_valueChanged(int value); void on_squelchGate_valueChanged(int value); + void on_spanLog2_valueChanged(int value); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); void handleInputMessages(); diff --git a/plugins/channelrx/freqtracker/freqtrackergui.ui b/plugins/channelrx/freqtracker/freqtrackergui.ui index 1419b08ed..4e88d0d5b 100644 --- a/plugins/channelrx/freqtracker/freqtrackergui.ui +++ b/plugins/channelrx/freqtracker/freqtrackergui.ui @@ -40,7 +40,7 @@ <x>0</x> <y>0</y> <width>401</width> - <height>140</height> + <height>151</height> </rect> </property> <property name="windowTitle"> @@ -673,15 +673,88 @@ </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="spanLayout"> + <item> + <widget class="QLabel" name="spanLabel"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Span</string> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="spanLog2"> + <property name="toolTip"> + <string>Spectrum display frequency span</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>6</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="spanText"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Spectrum display frequency span (kHz)</string> + </property> + <property name="text"> + <string>6.0k</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> <widget class="QWidget" name="spectrumContainer" native="true"> <property name="geometry"> <rect> <x>0</x> - <y>150</y> - <width>391</width> - <height>171</height> + <y>160</y> + <width>401</width> + <height>161</height> </rect> </property> <property name="windowTitle"> diff --git a/plugins/channelrx/freqtracker/freqtrackersettings.cpp b/plugins/channelrx/freqtracker/freqtrackersettings.cpp index bf187540d..96a831e01 100644 --- a/plugins/channelrx/freqtracker/freqtrackersettings.cpp +++ b/plugins/channelrx/freqtracker/freqtrackersettings.cpp @@ -37,6 +37,7 @@ void FreqTrackerSettings::resetToDefaults() m_squelch = -40.0; m_rgbColor = QColor(200, 244, 66).rgb(); m_title = "Frequency Tracker"; + m_spanLog2 = 0; m_alphaEMA = 0.1; m_tracking = false; m_trackerType = TrackerFLL; @@ -72,6 +73,7 @@ QByteArray FreqTrackerSettings::serialize() const s.writeFloat(8, m_alphaEMA); s.writeString(9, m_title); s.writeBool(10, m_tracking); + s.writeS32(11, m_spanLog2); s.writeS32(12, (int) m_trackerType); s.writeU32(13, m_pllPskOrder); s.writeBool(14, m_rrc); @@ -130,6 +132,7 @@ bool FreqTrackerSettings::deserialize(const QByteArray& data) m_alphaEMA = ftmp < 0.01 ? 0.01 : ftmp > 1.0 ? 1.0 : ftmp; d.readString(9, &m_title, "Frequency Tracker"); d.readBool(10, &m_tracking, false); + d.readS32(11, &m_spanLog2, 0); d.readS32(12, &tmp, 0); m_trackerType = tmp < 0 ? TrackerFLL : tmp > 2 ? TrackerPLL : (TrackerType) tmp; d.readU32(13, &utmp, 2); diff --git a/plugins/channelrx/freqtracker/freqtrackersettings.h b/plugins/channelrx/freqtracker/freqtrackersettings.h index 71e287f1e..c3ba9ef85 100644 --- a/plugins/channelrx/freqtracker/freqtrackersettings.h +++ b/plugins/channelrx/freqtracker/freqtrackersettings.h @@ -42,6 +42,7 @@ struct FreqTrackerSettings QString m_title; Serializable *m_channelMarker; Serializable *m_spectrumGUI; + int m_spanLog2; float m_alphaEMA; //!< alpha factor for delta frequency EMA bool m_tracking; TrackerType m_trackerType; diff --git a/plugins/channelrx/freqtracker/freqtrackersink.cpp b/plugins/channelrx/freqtracker/freqtrackersink.cpp index 4cbb8e85b..4b8ee1c78 100644 --- a/plugins/channelrx/freqtracker/freqtrackersink.cpp +++ b/plugins/channelrx/freqtracker/freqtrackersink.cpp @@ -36,6 +36,7 @@ FreqTrackerSink::FreqTrackerSink() : m_sinkSampleRate(48000), m_spectrumSink(nullptr), m_sampleBufferCount(0), + m_undersampleCount(0), m_squelchOpen(false), m_squelchGate(0), m_magsqSum(0.0f), @@ -57,6 +58,7 @@ FreqTrackerSink::FreqTrackerSink() : m_magsq = 0.0; m_sampleBufferSize = m_sinkSampleRate / 20; // 50 ms m_sampleBuffer.resize(m_sampleBufferSize); + m_sum = Complex{0.0, 0.0}; m_rrcFilter = new fftfilt(m_settings.m_rfBandwidth / m_sinkSampleRate, 2*1024); m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain @@ -107,7 +109,18 @@ void FreqTrackerSink::processOneSample(Complex &ci) { fftfilt::cmplx *sideband; int n_out; - m_sampleBuffer[m_sampleBufferCount++] = Sample(ci.real(), ci.imag()); + int decim = 1<<m_settings.m_spanLog2; + m_sum += ci; + + if (m_undersampleCount++ == decim) + { + Real avgr = m_sum.real() / decim; + Real avgi = m_sum.imag() / decim; + m_sampleBuffer[m_sampleBufferCount++] = Sample(avgr, avgi); + m_sum.real(0.0); + m_sum.imag(0.0); + m_undersampleCount = 0; + } if (m_settings.m_rrc) { @@ -230,9 +243,10 @@ void FreqTrackerSink::applyChannelSettings(int sinkSampleRate, int channelSample setInterpolator(); } - m_sampleBufferSize = m_sinkSampleRate / 20; // 50 ms + m_sampleBufferSize = (m_sinkSampleRate/(1<<m_settings.m_spanLog2)) / 20; // 50 ms m_sampleBuffer.resize(m_sampleBufferSize); m_sampleBufferCount = 0; + m_undersampleCount = 0; } void FreqTrackerSink::applySettings(const FreqTrackerSettings& settings, bool force) @@ -311,6 +325,14 @@ void FreqTrackerSink::applySettings(const FreqTrackerSettings& settings, bool fo useInterpolator = true; } + if ((settings.m_spanLog2 != m_settings.m_spanLog2) || force) + { + m_sampleBufferSize = (m_sinkSampleRate/(1<<settings.m_spanLog2)) / 20; // 50 ms + m_sampleBuffer.resize(m_sampleBufferSize); + m_sampleBufferCount = 0; + m_undersampleCount = 0; + } + m_settings = settings; if (useInterpolator) { diff --git a/plugins/channelrx/freqtracker/freqtrackersink.h b/plugins/channelrx/freqtracker/freqtrackersink.h index 3a9369f71..49ce5ab6c 100644 --- a/plugins/channelrx/freqtracker/freqtrackersink.h +++ b/plugins/channelrx/freqtracker/freqtrackersink.h @@ -105,6 +105,8 @@ private: SampleVector m_sampleBuffer; unsigned int m_sampleBufferCount; unsigned int m_sampleBufferSize; + Complex m_sum; + int m_undersampleCount; NCOF m_nco; PhaseLockComplex m_pll; diff --git a/plugins/channelrx/freqtracker/readme.md b/plugins/channelrx/freqtracker/readme.md index e72ae67b9..6457b9bb3 100644 --- a/plugins/channelrx/freqtracker/readme.md +++ b/plugins/channelrx/freqtracker/readme.md @@ -96,10 +96,14 @@ This indicator lights in green when the squelch is open. When the squelch is clo This is the squelch threshold in dB. The average total power received in the signal bandwidth before demodulation is compared to this value and the squelch input is open above this value. It can be varied continuously in 0.1 dB steps from 0.0 to -100.0 dB using the dial button. -<h4>10: Squelch time gate</h4> +<h3>10: Squelch time gate</h3> Number of milliseconds following squelch gate opening after which the signal is declared open. 0 means squelch is declared open with no delay and is suitable for burst signals. The value can be varied in steps of 10 ms from 0 to 990 ms. -<h4>11: Channel spectrum</h4> +<h3>11: Spectrum display frequency span</h3> -This is the spectrum display of the tracker channel. When the tracker is locked to the signal the center of the channel should fall almost in the middle of the signal spectrum (ideally in the middle when the tracker error is zero). Thus the locking can be followed dynamically and it can be more reliable than the lock indicator. A channel marker shows the tracker offset from the channel center frequency (tracker error). Its width is the tracker error tolerance but is hardly visible since it is 1/1000th of the channel width. Controls on the bottom of the panel are identical to the ones of the main spectrum display. +The channel signal is decimated by a power of two before being applied to the channel spectrum display. It is a kind of zoom on the center of the spectrum. + +<h3>12: Channel spectrum</h3> + +This is the spectrum display of the tracker channel. When the tracker is locked to the signal the center of the channel should fall almost in the middle of the signal spectrum (ideally in the middle when the tracker error is zero). Thus the locking can be followed dynamically and it can be more reliable than the lock indicator. A channel marker shows the tracker offset from the channel center frequency (tracker error). Its width is the tracker error tolerance and is ±1/1000th of the channel width. Controls on the bottom of the panel are identical to the ones of the main spectrum display. From 797bbdbac57fcdc42295a63ed9fc0852bb343c3f Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Mon, 26 Oct 2020 00:39:25 +0100 Subject: [PATCH 22/27] AFC: fixed channel tracking --- plugins/feature/afc/afcworker.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index 7ac54626f..77a40db59 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -287,20 +287,20 @@ void AFCWorker::processChannelSettings( if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) { - int channelOffset = channelOffsetValue.toInt(); - if (*swgChannelSettings->getChannelType() == "FreqTracker") { - if (channelOffset != m_trackerChannelOffset) + int trackerChannelOffset = channelOffsetValue.toInt(); + + if (trackerChannelOffset != m_trackerChannelOffset) { - qDebug("AFCWorker::processChannelSettings: FreqTracker offset change: %d", channelOffset); + qDebug("AFCWorker::processChannelSettings: FreqTracker offset change: %d", trackerChannelOffset); QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); for (; it != m_channelsMap.end(); ++it) { if (mainCore->existsChannel(it.key())) { - int channelOffset = it.value().m_channelOffset + channelOffset - it.value().m_trackerOffset; + int channelOffset = it.value().m_channelOffset + trackerChannelOffset - it.value().m_trackerOffset; updateChannelOffset(it.key(), it.value().m_channelDirection, channelOffset); } else @@ -309,17 +309,14 @@ void AFCWorker::processChannelSettings( } } - m_trackerChannelOffset = channelOffset; + m_trackerChannelOffset = trackerChannelOffset; } } else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) { - if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) - { - int channelOffset = channelOffsetValue.toInt(); - m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; - m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; - } + int channelOffset = channelOffsetValue.toInt(); + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; + m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; } } } From 8b188c420ddf3398b08ef5c03885996962a3a6cf Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Mon, 26 Oct 2020 06:15:02 +0100 Subject: [PATCH 23/27] AFC: REST API: actions and report --- swagger/sdrangel/api/swagger/include/AFC.yaml | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/swagger/sdrangel/api/swagger/include/AFC.yaml b/swagger/sdrangel/api/swagger/include/AFC.yaml index 03a62f97c..ebd836e63 100644 --- a/swagger/sdrangel/api/swagger/include/AFC.yaml +++ b/swagger/sdrangel/api/swagger/include/AFC.yaml @@ -30,7 +30,6 @@ AFCSettings: freqTolerance: descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted type: integer - format: int64 trackerAdjustPeriod: description: Tracker channel frequency adjustment period in seconds type: integer @@ -49,19 +48,29 @@ AFCSettings: AFCReport: description: "AFC report" properties: - ptt: + trackerChannelIndex: + description: Tracker index in device set + type: integer + trackerDeviceFrequency: + descritpion: Center frequency of tracker device + type: integer + format: int64 + trackerChannelOffset: + description: Tracker channel offset from device center frequency type: integer - description: > - AFC status - * 0 - released - * 1 - engaged AFCActions: description: "AFC actions" properties: - ptt: + deviceTrack: type: integer description: > - AFC action + (Re)initialize tracker target frequency adjustment + * 0 - release + * 1 - engage + devicesApply: + type: integer + description: > + (Re)initialize device sets tracking * 0 - release * 1 - engage From 598cefa93323e39728e1e986552c215b7cb57b26 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Tue, 27 Oct 2020 06:35:52 +0100 Subject: [PATCH 24/27] AFC: REST API: actions and report: generated code --- sdrbase/resources/webapi/doc/html2/index.html | 25 +++++-- .../webapi/doc/swagger/include/AFC.yaml | 25 ++++--- swagger/sdrangel/code/html2/index.html | 25 +++++-- .../code/qt5/client/SWGAFCActions.cpp | 49 +++++++++---- .../sdrangel/code/qt5/client/SWGAFCActions.h | 14 ++-- .../sdrangel/code/qt5/client/SWGAFCReport.cpp | 72 +++++++++++++++---- .../sdrangel/code/qt5/client/SWGAFCReport.h | 20 ++++-- .../code/qt5/client/SWGAFCSettings.cpp | 10 +-- .../sdrangel/code/qt5/client/SWGAFCSettings.h | 6 +- 9 files changed, 182 insertions(+), 64 deletions(-) diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index e643b84ad..c16f4ed7c 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -698,18 +698,30 @@ margin-bottom: 20px; var defs = {} defs.AFCActions = { "properties" : { - "ptt" : { + "deviceTrack" : { "type" : "integer", - "description" : "AFC action\n * 0 - release\n * 1 - engage\n" + "description" : "(Re)initialize tracker target frequency adjustment\n * 0 - release\n * 1 - engage\n" + }, + "devicesApply" : { + "type" : "integer", + "description" : "(Re)initialize device sets tracking\n * 0 - release\n * 1 - engage\n" } }, "description" : "AFC actions" }; defs.AFCReport = { "properties" : { - "ptt" : { + "trackerChannelIndex" : { "type" : "integer", - "description" : "AFC status\n * 0 - released\n * 1 - engaged\n" + "description" : "Tracker index in device set" + }, + "trackerDeviceFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "trackerChannelOffset" : { + "type" : "integer", + "description" : "Tracker channel offset from device center frequency" } }, "description" : "AFC report" @@ -744,8 +756,7 @@ margin-bottom: 20px; "description" : "Target frequency for the tracker" }, "freqTolerance" : { - "type" : "integer", - "format" : "int64" + "type" : "integer" }, "trackerAdjustPeriod" : { "type" : "integer", @@ -40055,7 +40066,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:29:00.746+01:00 + Generated 2020-10-27T06:34:40.143+01:00 </div> </div> </div> diff --git a/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml index 03a62f97c..ebd836e63 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/AFC.yaml @@ -30,7 +30,6 @@ AFCSettings: freqTolerance: descritpion: Frequency shift tolerance before tracker frequency is (re)adjusted type: integer - format: int64 trackerAdjustPeriod: description: Tracker channel frequency adjustment period in seconds type: integer @@ -49,19 +48,29 @@ AFCSettings: AFCReport: description: "AFC report" properties: - ptt: + trackerChannelIndex: + description: Tracker index in device set + type: integer + trackerDeviceFrequency: + descritpion: Center frequency of tracker device + type: integer + format: int64 + trackerChannelOffset: + description: Tracker channel offset from device center frequency type: integer - description: > - AFC status - * 0 - released - * 1 - engaged AFCActions: description: "AFC actions" properties: - ptt: + deviceTrack: type: integer description: > - AFC action + (Re)initialize tracker target frequency adjustment + * 0 - release + * 1 - engage + devicesApply: + type: integer + description: > + (Re)initialize device sets tracking * 0 - release * 1 - engage diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index e643b84ad..c16f4ed7c 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -698,18 +698,30 @@ margin-bottom: 20px; var defs = {} defs.AFCActions = { "properties" : { - "ptt" : { + "deviceTrack" : { "type" : "integer", - "description" : "AFC action\n * 0 - release\n * 1 - engage\n" + "description" : "(Re)initialize tracker target frequency adjustment\n * 0 - release\n * 1 - engage\n" + }, + "devicesApply" : { + "type" : "integer", + "description" : "(Re)initialize device sets tracking\n * 0 - release\n * 1 - engage\n" } }, "description" : "AFC actions" }; defs.AFCReport = { "properties" : { - "ptt" : { + "trackerChannelIndex" : { "type" : "integer", - "description" : "AFC status\n * 0 - released\n * 1 - engaged\n" + "description" : "Tracker index in device set" + }, + "trackerDeviceFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "trackerChannelOffset" : { + "type" : "integer", + "description" : "Tracker channel offset from device center frequency" } }, "description" : "AFC report" @@ -744,8 +756,7 @@ margin-bottom: 20px; "description" : "Target frequency for the tracker" }, "freqTolerance" : { - "type" : "integer", - "format" : "int64" + "type" : "integer" }, "trackerAdjustPeriod" : { "type" : "integer", @@ -40055,7 +40066,7 @@ except ApiException as e: </div> <div id="generator"> <div class="content"> - Generated 2020-10-27T06:29:00.746+01:00 + Generated 2020-10-27T06:34:40.143+01:00 </div> </div> </div> diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp index 357ca5338..96adf1fd1 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGAFCActions.cpp @@ -28,8 +28,10 @@ SWGAFCActions::SWGAFCActions(QString* json) { } SWGAFCActions::SWGAFCActions() { - ptt = 0; - m_ptt_isSet = false; + device_track = 0; + m_device_track_isSet = false; + devices_apply = 0; + m_devices_apply_isSet = false; } SWGAFCActions::~SWGAFCActions() { @@ -38,13 +40,16 @@ SWGAFCActions::~SWGAFCActions() { void SWGAFCActions::init() { - ptt = 0; - m_ptt_isSet = false; + device_track = 0; + m_device_track_isSet = false; + devices_apply = 0; + m_devices_apply_isSet = false; } void SWGAFCActions::cleanup() { + } SWGAFCActions* @@ -58,7 +63,9 @@ SWGAFCActions::fromJson(QString &json) { void SWGAFCActions::fromJsonObject(QJsonObject &pJson) { - ::SWGSDRangel::setValue(&ptt, pJson["ptt"], "qint32", ""); + ::SWGSDRangel::setValue(&device_track, pJson["deviceTrack"], "qint32", ""); + + ::SWGSDRangel::setValue(&devices_apply, pJson["devicesApply"], "qint32", ""); } @@ -76,21 +83,34 @@ SWGAFCActions::asJson () QJsonObject* SWGAFCActions::asJsonObject() { QJsonObject* obj = new QJsonObject(); - if(m_ptt_isSet){ - obj->insert("ptt", QJsonValue(ptt)); + if(m_device_track_isSet){ + obj->insert("deviceTrack", QJsonValue(device_track)); + } + if(m_devices_apply_isSet){ + obj->insert("devicesApply", QJsonValue(devices_apply)); } return obj; } qint32 -SWGAFCActions::getPtt() { - return ptt; +SWGAFCActions::getDeviceTrack() { + return device_track; } void -SWGAFCActions::setPtt(qint32 ptt) { - this->ptt = ptt; - this->m_ptt_isSet = true; +SWGAFCActions::setDeviceTrack(qint32 device_track) { + this->device_track = device_track; + this->m_device_track_isSet = true; +} + +qint32 +SWGAFCActions::getDevicesApply() { + return devices_apply; +} +void +SWGAFCActions::setDevicesApply(qint32 devices_apply) { + this->devices_apply = devices_apply; + this->m_devices_apply_isSet = true; } @@ -98,7 +118,10 @@ bool SWGAFCActions::isSet(){ bool isObjectUpdated = false; do{ - if(m_ptt_isSet){ + if(m_device_track_isSet){ + isObjectUpdated = true; break; + } + if(m_devices_apply_isSet){ isObjectUpdated = true; break; } }while(false); diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCActions.h b/swagger/sdrangel/code/qt5/client/SWGAFCActions.h index e25947dcc..7afe7c4d6 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCActions.h +++ b/swagger/sdrangel/code/qt5/client/SWGAFCActions.h @@ -41,15 +41,21 @@ public: virtual void fromJsonObject(QJsonObject &json) override; virtual SWGAFCActions* fromJson(QString &jsonString) override; - qint32 getPtt(); - void setPtt(qint32 ptt); + qint32 getDeviceTrack(); + void setDeviceTrack(qint32 device_track); + + qint32 getDevicesApply(); + void setDevicesApply(qint32 devices_apply); virtual bool isSet() override; private: - qint32 ptt; - bool m_ptt_isSet; + qint32 device_track; + bool m_device_track_isSet; + + qint32 devices_apply; + bool m_devices_apply_isSet; }; diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp index 89baca1eb..f577686c2 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGAFCReport.cpp @@ -28,8 +28,12 @@ SWGAFCReport::SWGAFCReport(QString* json) { } SWGAFCReport::SWGAFCReport() { - ptt = 0; - m_ptt_isSet = false; + tracker_channel_index = 0; + m_tracker_channel_index_isSet = false; + tracker_device_frequency = 0L; + m_tracker_device_frequency_isSet = false; + tracker_channel_offset = 0; + m_tracker_channel_offset_isSet = false; } SWGAFCReport::~SWGAFCReport() { @@ -38,13 +42,19 @@ SWGAFCReport::~SWGAFCReport() { void SWGAFCReport::init() { - ptt = 0; - m_ptt_isSet = false; + tracker_channel_index = 0; + m_tracker_channel_index_isSet = false; + tracker_device_frequency = 0L; + m_tracker_device_frequency_isSet = false; + tracker_channel_offset = 0; + m_tracker_channel_offset_isSet = false; } void SWGAFCReport::cleanup() { + + } SWGAFCReport* @@ -58,7 +68,11 @@ SWGAFCReport::fromJson(QString &json) { void SWGAFCReport::fromJsonObject(QJsonObject &pJson) { - ::SWGSDRangel::setValue(&ptt, pJson["ptt"], "qint32", ""); + ::SWGSDRangel::setValue(&tracker_channel_index, pJson["trackerChannelIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&tracker_device_frequency, pJson["trackerDeviceFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&tracker_channel_offset, pJson["trackerChannelOffset"], "qint32", ""); } @@ -76,21 +90,47 @@ SWGAFCReport::asJson () QJsonObject* SWGAFCReport::asJsonObject() { QJsonObject* obj = new QJsonObject(); - if(m_ptt_isSet){ - obj->insert("ptt", QJsonValue(ptt)); + if(m_tracker_channel_index_isSet){ + obj->insert("trackerChannelIndex", QJsonValue(tracker_channel_index)); + } + if(m_tracker_device_frequency_isSet){ + obj->insert("trackerDeviceFrequency", QJsonValue(tracker_device_frequency)); + } + if(m_tracker_channel_offset_isSet){ + obj->insert("trackerChannelOffset", QJsonValue(tracker_channel_offset)); } return obj; } qint32 -SWGAFCReport::getPtt() { - return ptt; +SWGAFCReport::getTrackerChannelIndex() { + return tracker_channel_index; } void -SWGAFCReport::setPtt(qint32 ptt) { - this->ptt = ptt; - this->m_ptt_isSet = true; +SWGAFCReport::setTrackerChannelIndex(qint32 tracker_channel_index) { + this->tracker_channel_index = tracker_channel_index; + this->m_tracker_channel_index_isSet = true; +} + +qint64 +SWGAFCReport::getTrackerDeviceFrequency() { + return tracker_device_frequency; +} +void +SWGAFCReport::setTrackerDeviceFrequency(qint64 tracker_device_frequency) { + this->tracker_device_frequency = tracker_device_frequency; + this->m_tracker_device_frequency_isSet = true; +} + +qint32 +SWGAFCReport::getTrackerChannelOffset() { + return tracker_channel_offset; +} +void +SWGAFCReport::setTrackerChannelOffset(qint32 tracker_channel_offset) { + this->tracker_channel_offset = tracker_channel_offset; + this->m_tracker_channel_offset_isSet = true; } @@ -98,7 +138,13 @@ bool SWGAFCReport::isSet(){ bool isObjectUpdated = false; do{ - if(m_ptt_isSet){ + if(m_tracker_channel_index_isSet){ + isObjectUpdated = true; break; + } + if(m_tracker_device_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_tracker_channel_offset_isSet){ isObjectUpdated = true; break; } }while(false); diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCReport.h b/swagger/sdrangel/code/qt5/client/SWGAFCReport.h index 8125dea81..81ba69f0c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGAFCReport.h @@ -41,15 +41,27 @@ public: virtual void fromJsonObject(QJsonObject &json) override; virtual SWGAFCReport* fromJson(QString &jsonString) override; - qint32 getPtt(); - void setPtt(qint32 ptt); + qint32 getTrackerChannelIndex(); + void setTrackerChannelIndex(qint32 tracker_channel_index); + + qint64 getTrackerDeviceFrequency(); + void setTrackerDeviceFrequency(qint64 tracker_device_frequency); + + qint32 getTrackerChannelOffset(); + void setTrackerChannelOffset(qint32 tracker_channel_offset); virtual bool isSet() override; private: - qint32 ptt; - bool m_ptt_isSet; + qint32 tracker_channel_index; + bool m_tracker_channel_index_isSet; + + qint64 tracker_device_frequency; + bool m_tracker_device_frequency_isSet; + + qint32 tracker_channel_offset; + bool m_tracker_channel_offset_isSet; }; diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp index 9fb6546a8..656f0b51b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.cpp @@ -42,7 +42,7 @@ SWGAFCSettings::SWGAFCSettings() { m_transverter_target_isSet = false; target_frequency = 0L; m_target_frequency_isSet = false; - freq_tolerance = 0L; + freq_tolerance = 0; m_freq_tolerance_isSet = false; tracker_adjust_period = 0; m_tracker_adjust_period_isSet = false; @@ -78,7 +78,7 @@ SWGAFCSettings::init() { m_transverter_target_isSet = false; target_frequency = 0L; m_target_frequency_isSet = false; - freq_tolerance = 0L; + freq_tolerance = 0; m_freq_tolerance_isSet = false; tracker_adjust_period = 0; m_tracker_adjust_period_isSet = false; @@ -141,7 +141,7 @@ SWGAFCSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&target_frequency, pJson["targetFrequency"], "qint64", ""); - ::SWGSDRangel::setValue(&freq_tolerance, pJson["freqTolerance"], "qint64", ""); + ::SWGSDRangel::setValue(&freq_tolerance, pJson["freqTolerance"], "qint32", ""); ::SWGSDRangel::setValue(&tracker_adjust_period, pJson["trackerAdjustPeriod"], "qint32", ""); @@ -287,12 +287,12 @@ SWGAFCSettings::setTargetFrequency(qint64 target_frequency) { this->m_target_frequency_isSet = true; } -qint64 +qint32 SWGAFCSettings::getFreqTolerance() { return freq_tolerance; } void -SWGAFCSettings::setFreqTolerance(qint64 freq_tolerance) { +SWGAFCSettings::setFreqTolerance(qint32 freq_tolerance) { this->freq_tolerance = freq_tolerance; this->m_freq_tolerance_isSet = true; } diff --git a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h index a05789594..02dfb2b5e 100644 --- a/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGAFCSettings.h @@ -63,8 +63,8 @@ public: qint64 getTargetFrequency(); void setTargetFrequency(qint64 target_frequency); - qint64 getFreqTolerance(); - void setFreqTolerance(qint64 freq_tolerance); + qint32 getFreqTolerance(); + void setFreqTolerance(qint32 freq_tolerance); qint32 getTrackerAdjustPeriod(); void setTrackerAdjustPeriod(qint32 tracker_adjust_period); @@ -109,7 +109,7 @@ private: qint64 target_frequency; bool m_target_frequency_isSet; - qint64 freq_tolerance; + qint32 freq_tolerance; bool m_freq_tolerance_isSet; qint32 tracker_adjust_period; From d0081b2af41146ed5d812004e3ea6429fc6f0c46 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Mon, 26 Oct 2020 13:48:19 +0100 Subject: [PATCH 25/27] AFC: REST API: actions and report: implementation --- plugins/feature/afc/afc.cpp | 49 +++++++++++++++++++++++++++---- plugins/feature/afc/afc.h | 4 ++- plugins/feature/afc/afcgui.cpp | 33 ++++++++++++--------- plugins/feature/afc/afcgui.h | 4 +-- plugins/feature/afc/afcreport.cpp | 2 +- plugins/feature/afc/afcreport.h | 17 ++++++----- plugins/feature/afc/afcworker.cpp | 18 ++++++++++-- plugins/feature/afc/afcworker.h | 3 ++ 8 files changed, 97 insertions(+), 33 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index 2b9c1cf33..9ae3f10f9 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -46,7 +46,8 @@ const QString AFC::m_featureId = "AFC"; AFC::AFC(WebAPIAdapterInterface *webAPIAdapterInterface) : Feature(m_featureIdURI, webAPIAdapterInterface), m_trackerDeviceSet(nullptr), - m_trackedDeviceSet(nullptr) + m_trackedDeviceSet(nullptr), + m_trackerIndexInDeviceSet(-1) { setObjectName(m_featureId); m_worker = new AFCWorker(webAPIAdapterInterface); @@ -61,7 +62,8 @@ AFC::~AFC() } delete m_worker; - removeFeatureReferences(); + removeTrackerFeatureReferences(); + removeTrackedFeatureReferences(); } void AFC::start() @@ -217,11 +219,13 @@ void AFC::applySettings(const AFCSettings& settings, bool force) reverseAPIKeys.append("trackerAdjustPeriod"); } - if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { + if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) + { trackerDeviceChange(settings.m_trackerDeviceSetIndex); } - if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) { + if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) + { trackedDeviceChange(settings.m_trackedDeviceSetIndex); } @@ -309,6 +313,28 @@ int AFC::webapiActionsPost( if (swgAFCActions) { + if (featureActionsKeys.contains("deviceTrack")) + { + bool deviceTrack = swgAFCActions->getDeviceTrack() != 0; + + if (deviceTrack) + { + MsgDeviceTrack *msg = MsgDeviceTrack::create(); + getInputMessageQueue()->push(msg); + } + } + + if (featureActionsKeys.contains("devicesApply")) + { + bool devicesApply = swgAFCActions->getDevicesApply() != 0; + + if (devicesApply) + { + MsgDevicesApply *msg = MsgDevicesApply::create(); + getInputMessageQueue()->push(msg); + } + } + return 202; } else @@ -401,6 +427,9 @@ void AFC::webapiUpdateFeatureSettings( void AFC::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response) { + response.getAfcReport()->setTrackerChannelIndex(m_trackerIndexInDeviceSet); + response.getAfcReport()->setTrackerDeviceFrequency(m_worker->getTrackerDeviceFrequency()); + response.getAfcReport()->setTrackerChannelOffset(m_worker->getTrackerChannelOffset()); } void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AFCSettings& settings, bool force) @@ -509,15 +538,18 @@ void AFC::trackedDeviceChange(int deviceIndex) { ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); - if (channel->getURI() != "sdrangel.channel.freqtracker") { + if (channel->getURI() != "sdrangel.channel.freqtracker") + { channel->addFeatureSettingsFeedback(this); + m_trackerIndexInDeviceSet = i; } } } -void AFC::removeFeatureReferences() +void AFC::removeTrackerFeatureReferences() { MainCore *mainCore = MainCore::instance(); + m_trackerIndexInDeviceSet = -1; if ((m_settings.m_trackerDeviceSetIndex >= 0) && (m_settings.m_trackerDeviceSetIndex < mainCore->getDeviceSets().size())) { @@ -532,6 +564,11 @@ void AFC::removeFeatureReferences() } } } +} + +void AFC::removeTrackedFeatureReferences() +{ + MainCore *mainCore = MainCore::instance(); if ((m_settings.m_trackedDeviceSetIndex >= 0) && (m_settings.m_trackedDeviceSetIndex < mainCore->getDeviceSets().size())) { diff --git a/plugins/feature/afc/afc.h b/plugins/feature/afc/afc.h index d29ba0ff8..6d169bbd1 100644 --- a/plugins/feature/afc/afc.h +++ b/plugins/feature/afc/afc.h @@ -160,6 +160,7 @@ private: AFCSettings m_settings; DeviceSet *m_trackerDeviceSet; DeviceSet *m_trackedDeviceSet; + int m_trackerIndexInDeviceSet; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -171,7 +172,8 @@ private: void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AFCSettings& settings, bool force); void trackerDeviceChange(int deviceIndex); void trackedDeviceChange(int deviceIndex); - void removeFeatureReferences(); + void removeTrackerFeatureReferences(); + void removeTrackedFeatureReferences(); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index 880989822..d2ac55ab4 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -79,15 +79,19 @@ bool AFCGUI::handleMessage(const Message& message) return true; } - else if (AFCReport::MsgRadioState::match(message)) + else if (AFCReport::MsgUpdateTarget::match(message)) { - qDebug("AFCGUI::handleMessage: AFCReport::MsgRadioState"); - const AFCReport::MsgRadioState& cfg = (AFCReport::MsgRadioState&) message; - AFCReport::RadioState state = cfg.getState(); - ui->statusIndicator->setStyleSheet("QLabel { background-color: " + - m_statusColors[(int) state] + "; border-radius: 12px; }"); - ui->statusIndicator->setToolTip(m_statusTooltips[(int) state]); + const AFCReport::MsgUpdateTarget& cfg = (AFCReport::MsgUpdateTarget&) message; + bool frequencyChanged = cfg.getFrequencyChanged(); + if (cfg.getFrequencyChanged()) { + ui->statusIndicator->setStyleSheet("QLabel { background-color: rgb(232, 85, 85); border-radius: 8px; }"); // red + } else { + ui->statusIndicator->setStyleSheet("QLabel { background-color: rgb(85, 232, 85); border-radius: 8px; }"); // green + } + + ui->statusIndicator->setToolTip(tr("%1 Hz").arg(cfg.getFrequencyAdjustment())); + m_autoTargetStatusTimer.start(500); return true; } @@ -142,13 +146,9 @@ AFCGUI::AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(1000); - m_statusTooltips.push_back("Idle"); // 0 - all off - m_statusTooltips.push_back("Rx on"); // 1 - Rx on - m_statusTooltips.push_back("Tx on"); // 2 - Tx on - - m_statusColors.push_back("gray"); // All off - m_statusColors.push_back("rgb(85, 232, 85)"); // Rx on (green) - m_statusColors.push_back("rgb(232, 85, 85)"); // Tx on (red) + connect(&m_autoTargetStatusTimer, SIGNAL(timeout()), this, SLOT(resetAutoTargetStatus())); + m_autoTargetStatusTimer.setSingleShot(true); + ui->statusIndicator->setStyleSheet("QLabel { background-color: gray; border-radius: 8px; }"); updateDeviceSetLists(); displaySettings(); @@ -401,6 +401,11 @@ void AFCGUI::updateStatus() } } +void AFCGUI::resetAutoTargetStatus() +{ + ui->statusIndicator->setStyleSheet("QLabel { background-color: gray; border-radius: 8px; }"); +} + void AFCGUI::applySettings(bool force) { if (m_doApplySettings) diff --git a/plugins/feature/afc/afcgui.h b/plugins/feature/afc/afcgui.h index d4bfa2b14..b9adbe79b 100644 --- a/plugins/feature/afc/afcgui.h +++ b/plugins/feature/afc/afcgui.h @@ -53,9 +53,8 @@ private: AFC* m_afc; MessageQueue m_inputMessageQueue; QTimer m_statusTimer; + QTimer m_autoTargetStatusTimer; int m_lastFeatureState; - std::vector<QString> m_statusColors; - std::vector<QString> m_statusTooltips; explicit AFCGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr); virtual ~AFCGUI(); @@ -85,6 +84,7 @@ private slots: void on_devicesApply_clicked(); void on_targetPeriod_valueChanged(int value); void updateStatus(); + void resetAutoTargetStatus(); }; diff --git a/plugins/feature/afc/afcreport.cpp b/plugins/feature/afc/afcreport.cpp index 105de5d52..a9ced7006 100644 --- a/plugins/feature/afc/afcreport.cpp +++ b/plugins/feature/afc/afcreport.cpp @@ -17,7 +17,7 @@ #include "afcreport.h" -MESSAGE_CLASS_DEFINITION(AFCReport::MsgRadioState, Message) +MESSAGE_CLASS_DEFINITION(AFCReport::MsgUpdateTarget, Message) AFCReport::AFCReport() {} diff --git a/plugins/feature/afc/afcreport.h b/plugins/feature/afc/afcreport.h index 97f94f99d..47b6bf8ef 100644 --- a/plugins/feature/afc/afcreport.h +++ b/plugins/feature/afc/afcreport.h @@ -28,23 +28,26 @@ public: RadioRx, RadioTx }; - class MsgRadioState : public Message { + class MsgUpdateTarget : public Message { MESSAGE_CLASS_DECLARATION public: - RadioState getState() const { return m_state; } + int getFrequencyAdjustment() const { return m_frequencyAdjustment; } + bool getFrequencyChanged() const { return m_frequencyChanged; } - static MsgRadioState* create(RadioState state) + static MsgUpdateTarget* create(int frequencyAdjustment, bool frequencyChanged) { - return new MsgRadioState(state); + return new MsgUpdateTarget(frequencyAdjustment, frequencyChanged); } private: - RadioState m_state; + int m_frequencyAdjustment; + bool m_frequencyChanged; - MsgRadioState(RadioState state) : + MsgUpdateTarget(int frequencyAdjustment, bool frequencyChanged) : Message(), - m_state(state) + m_frequencyAdjustment(frequencyAdjustment), + m_frequencyChanged(frequencyChanged) { } }; diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index 77a40db59..f0decea34 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -393,9 +393,10 @@ void AFCWorker::updateTarget() int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; int64_t correction = m_settings.m_targetFrequency - trackerFrequency; int64_t tolerance = m_settings.m_freqTolerance; - qDebug() << "AFCWorker::updateTarget: correction:" << correction << "tolerance:" << tolerance; - if ((correction > -tolerance) && (correction < tolerance)) { + if ((correction > -tolerance) && (correction < tolerance)) + { + reportUpdateTarget(correction, false); return; } @@ -420,6 +421,8 @@ void AFCWorker::updateTarget() if (updateChannelOffset(m_freqTracker, 0, m_trackerChannelOffset + correction, 1)) { m_trackerChannelOffset += correction; } + + reportUpdateTarget(correction, true); } else // act on device { @@ -436,6 +439,8 @@ void AFCWorker::updateTarget() qDebug() << "AFCWorker::updateTarget: cannot find device transverter frequency"; return; } + + reportUpdateTarget(correction, true); } } @@ -515,3 +520,12 @@ void AFCWorker::getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey) } } } + +void AFCWorker::reportUpdateTarget(int correction, bool done) +{ + if (m_msgQueueToGUI) + { + AFCReport::MsgUpdateTarget *msg = AFCReport::MsgUpdateTarget::create(correction, done); + m_msgQueueToGUI->push(msg); + } +} diff --git a/plugins/feature/afc/afcworker.h b/plugins/feature/afc/afcworker.h index d1fc10140..862e22607 100644 --- a/plugins/feature/afc/afcworker.h +++ b/plugins/feature/afc/afcworker.h @@ -112,6 +112,8 @@ public: bool isRunning() const { return m_running; } MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; } + uint64_t getTrackerDeviceFrequency() const { return m_trackerDeviceFrequency; } + int getTrackerChannelOffset() const { return m_trackerChannelOffset; } private: struct ChannelTracking @@ -166,6 +168,7 @@ private: bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); int getDeviceDirection(DeviceAPI *deviceAPI); void getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey); + void reportUpdateTarget(int correction, bool done); private slots: void updateTarget(); From b5162dfc5fe8ada9eab8d79b17fbaaaf3a1ced3b Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Mon, 26 Oct 2020 21:39:34 +0100 Subject: [PATCH 26/27] AFC: fixes. Implement devices apply and reset channels feedbac --- plugins/feature/afc/afc.cpp | 48 ++++++++++++++----------------- plugins/feature/afc/afc.h | 4 ++- plugins/feature/afc/afcgui.cpp | 3 +- plugins/feature/afc/afcworker.cpp | 5 ++-- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/plugins/feature/afc/afc.cpp b/plugins/feature/afc/afc.cpp index 9ae3f10f9..48f2ecdd0 100644 --- a/plugins/feature/afc/afc.cpp +++ b/plugins/feature/afc/afc.cpp @@ -47,7 +47,8 @@ AFC::AFC(WebAPIAdapterInterface *webAPIAdapterInterface) : Feature(m_featureIdURI, webAPIAdapterInterface), m_trackerDeviceSet(nullptr), m_trackedDeviceSet(nullptr), - m_trackerIndexInDeviceSet(-1) + m_trackerIndexInDeviceSet(-1), + m_trackerChannelAPI(nullptr) { setObjectName(m_featureId); m_worker = new AFCWorker(webAPIAdapterInterface); @@ -62,7 +63,7 @@ AFC::~AFC() } delete m_worker; - removeTrackerFeatureReferences(); + removeTrackerFeatureReference(); removeTrackedFeatureReferences(); } @@ -141,6 +142,11 @@ bool AFC::handleMessage(const Message& cmd) } else if (MsgDevicesApply::match(cmd)) { + removeTrackerFeatureReference(); + trackerDeviceChange(m_settings.m_trackerDeviceSetIndex); + removeTrackedFeatureReferences(); + trackedDeviceChange(m_settings.m_trackedDeviceSetIndex); + if (m_worker->isRunning()) { AFCWorker::MsgDevicesApply *msg = AFCWorker::MsgDevicesApply::create(); @@ -221,11 +227,13 @@ void AFC::applySettings(const AFCSettings& settings, bool force) if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { + removeTrackerFeatureReference(); trackerDeviceChange(settings.m_trackerDeviceSetIndex); } if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) { + removeTrackedFeatureReferences(); trackedDeviceChange(settings.m_trackedDeviceSetIndex); } @@ -524,6 +532,7 @@ void AFC::trackerDeviceChange(int deviceIndex) if (channel->getURI() == "sdrangel.channel.freqtracker") { channel->addFeatureSettingsFeedback(this); + m_trackerChannelAPI = channel; break; } } @@ -546,41 +555,26 @@ void AFC::trackedDeviceChange(int deviceIndex) } } -void AFC::removeTrackerFeatureReferences() +void AFC::removeTrackerFeatureReference() { - MainCore *mainCore = MainCore::instance(); - m_trackerIndexInDeviceSet = -1; - - if ((m_settings.m_trackerDeviceSetIndex >= 0) && (m_settings.m_trackerDeviceSetIndex < mainCore->getDeviceSets().size())) + if (m_trackerChannelAPI) { - DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackerDeviceSetIndex]; - - if (trackerDeviceSet == m_trackerDeviceSet) - { - for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) - { - ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); - channel->removeFeatureSettingsFeedback(this); - } + if (MainCore::instance()->existsChannel(m_trackerChannelAPI)) { + m_trackerChannelAPI->removeFeatureSettingsFeedback(this); } } } void AFC::removeTrackedFeatureReferences() { - MainCore *mainCore = MainCore::instance(); - - if ((m_settings.m_trackedDeviceSetIndex >= 0) && (m_settings.m_trackedDeviceSetIndex < mainCore->getDeviceSets().size())) + for (QList<ChannelAPI*>::iterator it = m_trackedChannelAPIs.begin(); it != m_trackedChannelAPIs.end(); ++it) { - DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackedDeviceSetIndex]; + ChannelAPI *channel = *it; - if (trackerDeviceSet == m_trackedDeviceSet) - { - for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) - { - ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); - channel->removeFeatureSettingsFeedback(this); - } + if (MainCore::instance()->existsChannel(channel)) { + channel->removeFeatureSettingsFeedback(this); } } + + m_trackedChannelAPIs.clear(); } diff --git a/plugins/feature/afc/afc.h b/plugins/feature/afc/afc.h index 6d169bbd1..a735f42db 100644 --- a/plugins/feature/afc/afc.h +++ b/plugins/feature/afc/afc.h @@ -161,6 +161,8 @@ private: DeviceSet *m_trackerDeviceSet; DeviceSet *m_trackedDeviceSet; int m_trackerIndexInDeviceSet; + ChannelAPI *m_trackerChannelAPI; + QList<ChannelAPI*> m_trackedChannelAPIs; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -172,7 +174,7 @@ private: void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AFCSettings& settings, bool force); void trackerDeviceChange(int deviceIndex); void trackedDeviceChange(int deviceIndex); - void removeTrackerFeatureReferences(); + void removeTrackerFeatureReference(); void removeTrackedFeatureReferences(); private slots: diff --git a/plugins/feature/afc/afcgui.cpp b/plugins/feature/afc/afcgui.cpp index d2ac55ab4..c33552469 100644 --- a/plugins/feature/afc/afcgui.cpp +++ b/plugins/feature/afc/afcgui.cpp @@ -362,7 +362,8 @@ void AFCGUI::on_trackedDevice_currentIndexChanged(int index) void AFCGUI::on_devicesApply_clicked() { - + AFC::MsgDevicesApply *msg = AFC::MsgDevicesApply::create(); + m_afc->getInputMessageQueue()->push(msg); } void AFCGUI::on_targetPeriod_valueChanged(int value) diff --git a/plugins/feature/afc/afcworker.cpp b/plugins/feature/afc/afcworker.cpp index f0decea34..6d6c2aec4 100644 --- a/plugins/feature/afc/afcworker.cpp +++ b/plugins/feature/afc/afcworker.cpp @@ -119,12 +119,14 @@ bool AFCWorker::handleMessage(const Message& cmd) } else if (MsgDeviceTrack::match(cmd)) { + qDebug() << "AFCWorker::handleMessage: MsgDeviceTrack"; QMutexLocker mutexLocker(&m_mutex); updateTarget(); return true; } else if (MsgDevicesApply::match(cmd)) { + qDebug() << "AFCWorker::handleMessage: MsgDevicesApply"; QMutexLocker mutexLocker(&m_mutex); initTrackerDeviceSet(m_settings.m_trackerDeviceSetIndex); initTrackedDeviceSet(m_settings.m_trackedDeviceSetIndex); @@ -294,6 +296,7 @@ void AFCWorker::processChannelSettings( if (trackerChannelOffset != m_trackerChannelOffset) { qDebug("AFCWorker::processChannelSettings: FreqTracker offset change: %d", trackerChannelOffset); + m_trackerChannelOffset = trackerChannelOffset; QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); for (; it != m_channelsMap.end(); ++it) @@ -308,8 +311,6 @@ void AFCWorker::processChannelSettings( m_channelsMap.erase(it); } } - - m_trackerChannelOffset = trackerChannelOffset; } } else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) From b604eeeaa0dd6df53ec129bbcd332ffd50c20771 Mon Sep 17 00:00:00 2001 From: f4exb <f4exb06@gmail.com> Date: Tue, 27 Oct 2020 22:33:39 +0100 Subject: [PATCH 27/27] AFC: added documentation --- doc/img/AFC_plugin.png | Bin 0 -> 19854 bytes doc/img/AFC_plugin.xcf | Bin 0 -> 80950 bytes plugins/feature/afc/readme.md | 60 +++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 doc/img/AFC_plugin.png create mode 100644 doc/img/AFC_plugin.xcf diff --git a/doc/img/AFC_plugin.png b/doc/img/AFC_plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..3180605df593d1088e93daedc8d7ff193da25a23 GIT binary patch literal 19854 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 literal 0 HcmV?d00001 diff --git a/doc/img/AFC_plugin.xcf b/doc/img/AFC_plugin.xcf new file mode 100644 index 0000000000000000000000000000000000000000..92c019b8d43ab17c9255298bb41964dda3056843 GIT binary patch literal 80950 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 ZOUwXYI;A~XoEWV%VvSd5$5R@0{|}BSU^oB( literal 0 HcmV?d00001 diff --git a/plugins/feature/afc/readme.md b/plugins/feature/afc/readme.md index 6d60f5b16..573280371 100644 --- a/plugins/feature/afc/readme.md +++ b/plugins/feature/afc/readme.md @@ -1,8 +1,8 @@ -<h1>AFC plugin</h1> +<h1>Automatic Frequency Control plugin</h1> <h2>Introduction</h2> -This plugin controls switchover between a Rx (Device source) and Tx (Device sink). It has no other controls than an adjustable delay from Rx to Tx and back to Rx. Because of its simplicity it can also serve as a model to build other feature plugins. +This plugin makes the link between a [frequency tracker](../../channelrx/freqtracker/readme.md) and other channels in order to have them controlled by the frequency tracker. Thus it closes the loop to effectively make an automatic frequency control system. <h2>Interface</h2> @@ -12,34 +12,56 @@ This plugin controls switchover between a Rx (Device source) and Tx (Device sink This button starts or stops the plugin -<h3>2: PTT button</h3> +<h3>2: Update device sets lists</h3> -Click to switch from Rx to Tx and again to switch back to Rx. When in Tx mode the button is lit. +It updates the tracker device set and tracked device set combo boxes (3) and (4) respectively with the available device sets. -<h3>3: Status indicator</h3> +<h3>3: Tracker device set selection</h3> -This LED type display shows the current PTT status: +The first frequency tracker in this device set will be used to control frequency. Thus only Rx device sets can be selected. - - **Green**: Rx runs - - **Red**: Tx runs - - **Grey**: None active (transient) +<h3>4: Tracked device set selection</h3> -<h3>4: Refresh list of devices</h3> +All channels but frequency tracker(s) in this device set will have their offset frequency controlled by the frequency tracker selected with (3). -Use this button to refresh the list of devices (5) and (6) +<h3>5: (Re)apply device sets selection</h3> -<h3>5: Select Rx device set</h3> +Use this button to force evaluation of selected device sets i.e. the first frequency tracker used for tracking and the tracked channels. -Use this combo to select which Rx device is controlled +<h3>6: Automatic target frequency readjustment</h3> -<h3>6: Select Tx device set</h3> +When the frequency tracker drifts following the signal it is tracking its effective frequency will move accordingly. To avoid it going too far from a nominal frequency set by (7) the device or transverter frequency can be used to re-adjust the frequency tracker center frequency periodically. -Use this combo to select which Tx device is controlled +<h3>7: Tracker target frequency</h3> -<h3>7: Transistion delay from Rx to Tx</h3> +This is the nominal frequency of the signal being tracked. For example (as in the picture) when tracking the QO-100 center beacon this is 10489.750 MHz thus with the transverter shift set at -250 kHz this is 489.750 MHz (The actual downconverted Rx frequency is 739.750 MHz). -Value in milliseconds between Rx stop and Tx start +<h3>8: Use transverter shift to adjust target frequency</h3> -<h3>8: Transistion delay from Tx to Rx</h3> +When unset the device center frequency is used and when set the device center frequency setting is unchanged and the transverter shift is adjusted. -Value in milliseconds between Tx stop and Rx start +You would use the transverter adjustment for QO-100 tracking for example thus the resulting IF frequency is unchanged maintaining the center beacon around 489.750 MHz. + +The transverter shift can be adjusted down to the Hz but depending on the device actual steps such granularity may not be effectively achievable. + +<h3>9: Target frequency tolerance</h3> + +Frequency readjustment will actually take place only if the frequency tracker frequency moves further away than ± this value from the nominal frequency (7). + +You should not choose a value that is too tight else the frequency tracker frequency will keep moving around the target frequency without stabilizing. In practice you may set a low value and trigger a single shot adjustment with the (11) button and once stabilized choose a value significantly higher than the offset from nominal that is obtained. + +Please note that if the device frequency adjustment is used the steps are in kHz so multiples of the kHz should be used. + +<h3>10. Target frequency readjustment period (seconds)</h3> + +The target frequency readjustment is periodically activated and frequency change is effectively activated if the tracker frequency offset from nominal is larger than the tolerance (9). + +Depending on how fast the frequency drift occurs you should set a value in combination with the frequency tolerance (9) so that the frequency is not readjusted too frequently. + +<h3>11. Activate target frequency readjustment immediately</h3> + +This forces target readjustment process described above immediately. + +<h3>12. Target readjustement indicator</h3> + +This indicator will flash briefly when the readjustment process takes place. Its color is green if the frequency is not changed and is red if frequency changes. The tooltip shows the last frequency difference that was calculated.