diff --git a/doc/img/AaroniaRTSAInput.png b/doc/img/AaroniaRTSAInput.png new file mode 100644 index 000000000..66b979fc1 Binary files /dev/null and b/doc/img/AaroniaRTSAInput.png differ diff --git a/doc/img/AaroniaRTSAInput.xcf b/doc/img/AaroniaRTSAInput.xcf new file mode 100644 index 000000000..e477f29ba Binary files /dev/null and b/doc/img/AaroniaRTSAInput.xcf differ diff --git a/doc/img/AaroniaRTSAInput_mission.png b/doc/img/AaroniaRTSAInput_mission.png new file mode 100644 index 000000000..ff4eabc6e Binary files /dev/null and b/doc/img/AaroniaRTSAInput_mission.png differ diff --git a/doc/img/AaroniaRTSAInput_mission.xcf b/doc/img/AaroniaRTSAInput_mission.xcf new file mode 100644 index 000000000..0b9238cb6 Binary files /dev/null and b/doc/img/AaroniaRTSAInput_mission.xcf differ diff --git a/doc/img/AaroniaRTSAInput_sdrangel.png b/doc/img/AaroniaRTSAInput_sdrangel.png new file mode 100644 index 000000000..c5bbc2e9a Binary files /dev/null and b/doc/img/AaroniaRTSAInput_sdrangel.png differ diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index b241f0209..938c639ae 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -751,8 +751,13 @@ void DATVDemodGUI::on_spiSymbolRate_valueChanged(int value) void DATVDemodGUI::on_datvStdSR_valueChanged(int value) { m_settings.m_symbolRate = symbolRateFromIndex(value); + m_settings.m_rfBandwidth = (m_settings.m_symbolRate * 3) / 2; ui->spiSymbolRate->blockSignals(true); + ui->rfBandwidth->blockSignals(true); ui->spiSymbolRate->setValue(m_settings.m_symbolRate); + ui->rfBandwidth->setValue(m_settings.m_rfBandwidth); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + ui->rfBandwidth->blockSignals(false); ui->spiSymbolRate->blockSignals(false); applySettings(); } diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index f32e76eb0..0f5f805a4 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -73,3 +73,4 @@ endif() add_subdirectory(audioinput) add_subdirectory(kiwisdr) add_subdirectory(remotetcpinput) +add_subdirectory(aaroniartsainput) diff --git a/plugins/samplesource/aaroniartsainput/CMakeLists.txt b/plugins/samplesource/aaroniartsainput/CMakeLists.txt new file mode 100644 index 000000000..8336c83fa --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/CMakeLists.txt @@ -0,0 +1,63 @@ +project(aaroniartsainput) + +set(aaroniartsainput_SOURCES + aaroniartsainput.cpp + aaroniartsainputplugin.cpp + aaroniartsainputworker.cpp + aaroniartsainputsettings.cpp + aaroniartsainputwebapiadapter.cpp +) + +set(aaroniartsainput_HEADERS + aaroniartsainput.h + aaroniartsainputplugin.h + aaroniartsainputworker.h + aaroniartsainputsettings.h + aaroniartsainputwebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${Boost_INCLUDE_DIRS} +) + +if(NOT SERVER_MODE) + set(aaroniartsainput_SOURCES + ${aaroniartsainput_SOURCES} + aaroniartsainputgui.cpp + aaroniartsainputgui.ui + ) + set(aaroniartsainput_HEADERS + ${aaroniartsainput_HEADERS} + aaroniartsainputgui.h + ) + + set(TARGET_NAME inputaaroniartsa) + set(TARGET_LIB "Qt::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME inputaaroniartsasrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${aaroniartsainput_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt::Core + Qt::WebSockets + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) + +# Install debug symbols +if (WIN32) + install(FILES $ CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} ) +endif() diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainput.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainput.cpp new file mode 100644 index 000000000..6b629e382 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainput.cpp @@ -0,0 +1,535 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include +#include +#include +#include +#include + +#include "SWGDeviceSettings.h" +#include "SWGDeviceState.h" +#include "SWGDeviceReport.h" +#include "SWGAaroniaRTSAReport.h" + +#include "aaroniartsainput.h" +#include "device/deviceapi.h" +#include "aaroniartsainputworker.h" +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" + +MESSAGE_CLASS_DEFINITION(AaroniaRTSAInput::MsgConfigureAaroniaRTSA, Message) +MESSAGE_CLASS_DEFINITION(AaroniaRTSAInput::MsgStartStop, Message) +MESSAGE_CLASS_DEFINITION(AaroniaRTSAInput::MsgSetStatus, Message) + + +AaroniaRTSAInput::AaroniaRTSAInput(DeviceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_sampleRate(10000000), + m_centerFrequency(1450000), + m_settings(), + m_aaroniaRTSAWorker(nullptr), + m_aaroniaRTSAWorkerThread(nullptr), + m_deviceDescription("AaroniaRTSA"), + m_running(false), + m_masterTimer(deviceAPI->getMasterTimer()) +{ + m_sampleFifo.setLabel(m_deviceDescription); + m_deviceAPI->setNbSourceStreams(1); + + if (!m_sampleFifo.setSize(getSampleRate() * 2)) { + qCritical("AaroniaRTSAInput::AaroniaRTSAInput: Could not allocate SampleFifo"); + } + + m_networkManager = new QNetworkAccessManager(); + QObject::connect( + m_networkManager, + &QNetworkAccessManager::finished, + this, + &AaroniaRTSAInput::networkManagerFinished + ); +} + +AaroniaRTSAInput::~AaroniaRTSAInput() +{ + QObject::disconnect( + m_networkManager, + &QNetworkAccessManager::finished, + this, + &AaroniaRTSAInput::networkManagerFinished + ); + delete m_networkManager; + + if (m_running) { + stop(); + } +} + +void AaroniaRTSAInput::destroy() +{ + delete this; +} + +void AaroniaRTSAInput::init() +{ + applySettings(m_settings, QList(), true); +} + +bool AaroniaRTSAInput::start() +{ + QMutexLocker mutexLocker(&m_mutex); + + if (m_running) { + return true; + } + + m_aaroniaRTSAWorkerThread = new QThread(); + m_aaroniaRTSAWorker = new AaroniaRTSAInputWorker(&m_sampleFifo); + m_aaroniaRTSAWorker->setInputMessageQueue(getInputMessageQueue()); + m_aaroniaRTSAWorker->moveToThread(m_aaroniaRTSAWorkerThread); + + QObject::connect(m_aaroniaRTSAWorkerThread, &QThread::finished, m_aaroniaRTSAWorker, &QObject::deleteLater); + QObject::connect(m_aaroniaRTSAWorkerThread, &QThread::finished, m_aaroniaRTSAWorkerThread, &QThread::deleteLater); + + connect(this, &AaroniaRTSAInput::setWorkerCenterFrequency, m_aaroniaRTSAWorker, &AaroniaRTSAInputWorker::onCenterFrequencyChanged); + connect(this, &AaroniaRTSAInput::setWorkerSampleRate, m_aaroniaRTSAWorker, &AaroniaRTSAInputWorker::onSampleRateChanged); + connect(this, &AaroniaRTSAInput::setWorkerServerAddress, m_aaroniaRTSAWorker, &AaroniaRTSAInputWorker::onServerAddressChanged); + connect(m_aaroniaRTSAWorker, &AaroniaRTSAInputWorker::updateStatus, this, &AaroniaRTSAInput::setWorkerStatus); + + m_aaroniaRTSAWorkerThread->start(); + m_running = true; + + mutexLocker.unlock(); + applySettings(m_settings, QList(), true); + + return true; +} + +void AaroniaRTSAInput::stop() +{ + QMutexLocker mutexLocker(&m_mutex); + + if (!m_running) { + return; + } + + m_running = false; + setWorkerStatus(0); + + if (m_aaroniaRTSAWorkerThread) + { + m_aaroniaRTSAWorkerThread->quit(); + m_aaroniaRTSAWorkerThread->wait(); + m_aaroniaRTSAWorker = nullptr; + m_aaroniaRTSAWorkerThread = nullptr; + } +} + +QByteArray AaroniaRTSAInput::serialize() const +{ + return m_settings.serialize(); +} + +bool AaroniaRTSAInput::deserialize(const QByteArray& data) +{ + bool success = true; + + if (!m_settings.deserialize(data)) + { + m_settings.resetToDefaults(); + success = false; + } + + MsgConfigureAaroniaRTSA* message = MsgConfigureAaroniaRTSA::create(m_settings, QList(), true); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureAaroniaRTSA* messageToGUI = MsgConfigureAaroniaRTSA::create(m_settings, QList(), true); + m_guiMessageQueue->push(messageToGUI); + } + + return success; +} + +const QString& AaroniaRTSAInput::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int AaroniaRTSAInput::getSampleRate() const +{ + return m_sampleRate; +} + +quint64 AaroniaRTSAInput::getCenterFrequency() const +{ + return m_settings.m_centerFrequency; +} + +void AaroniaRTSAInput::setCenterFrequency(qint64 centerFrequency) +{ + AaroniaRTSAInputSettings settings = m_settings; + settings.m_centerFrequency = centerFrequency; + + MsgConfigureAaroniaRTSA* message = MsgConfigureAaroniaRTSA::create(settings, QList{"centerFrequency"}, false); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureAaroniaRTSA* messageToGUI = MsgConfigureAaroniaRTSA::create(settings, QList{"centerFrequency"}, false); + m_guiMessageQueue->push(messageToGUI); + } +} + +void AaroniaRTSAInput::setWorkerStatus(int status) +{ + if (m_guiMessageQueue) { + m_guiMessageQueue->push(MsgSetStatus::create(status)); + } +} + +bool AaroniaRTSAInput::handleMessage(const Message& message) +{ + if (MsgConfigureAaroniaRTSA::match(message)) + { + MsgConfigureAaroniaRTSA& conf = (MsgConfigureAaroniaRTSA&) message; + qDebug() << "AaroniaRTSAInput::handleMessage: MsgConfigureAaroniaRTSA"; + + bool success = applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce()); + + if (!success) { + qDebug("AaroniaRTSAInput::handleMessage: config error"); + } + + return true; + } + else if (AaroniaRTSAInputWorker::MsgReportSampleRateAndFrequency::match(message)) + { + AaroniaRTSAInputWorker::MsgReportSampleRateAndFrequency& report = (AaroniaRTSAInputWorker::MsgReportSampleRateAndFrequency&) message; + m_sampleRate = report.getSampleRate(); + m_centerFrequency = report.getCenterFrequency(); + qDebug() << "AaroniaRTSAInput::handleMessage: AaroniaRTSAInputWorker::MsgReportSampleRateAndFrequency:" + << " m_sampleRate: " << m_sampleRate + << " m-centerFrequency" << m_centerFrequency; + + if (!m_sampleFifo.setSize(m_sampleRate * 2)) { + qCritical("AaroniaRTSAInput::AaroniaRTSAInput: Could not allocate SampleFifo"); + } + + DSPSignalNotification *notif = new DSPSignalNotification( + m_sampleRate, m_centerFrequency); + m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); + + return true; + } + else if (MsgStartStop::match(message)) + { + MsgStartStop& cmd = (MsgStartStop&) message; + qDebug() << "AaroniaRTSAInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); + + if (cmd.getStartStop()) + { + if (m_deviceAPI->initDeviceEngine()) { + m_deviceAPI->startDeviceEngine(); + } + } + else + { + m_deviceAPI->stopDeviceEngine(); + } + + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + + return true; + } + else + { + return false; + } +} + +int AaroniaRTSAInput::getStatus() const +{ + if (m_aaroniaRTSAWorker) { + return m_aaroniaRTSAWorker->getStatus(); + } else { + return 0; + } +} + +bool AaroniaRTSAInput::applySettings(const AaroniaRTSAInputSettings& settings, const QList& settingsKeys, bool force) +{ + qDebug() << "AaroniaRTSAInput::applySettings: force: "<< force << settings.getDebugString(settingsKeys, force); + + if (settingsKeys.contains("serverAddress") || force) + { + emit setWorkerServerAddress(settings.m_serverAddress); + } + + if (settingsKeys.contains("centerFrequency") || force) + { + emit setWorkerCenterFrequency(settings.m_centerFrequency); + + // DSPSignalNotification *notif = new DSPSignalNotification( + // getSampleRate(), settings.m_centerFrequency); + // m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); + } + + if (settingsKeys.contains("sampleRate")) { + emit setWorkerSampleRate(settings.m_sampleRate); + } + + if (settingsKeys.contains("useReverseAPI")) + { + bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) || + settingsKeys.contains("reverseAPIAddress") || + settingsKeys.contains("reverseAPIPort") || + settingsKeys.contains("reverseAPIDeviceIndex"); + webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force); + } + + if (force) { + m_settings = settings; + } else { + m_settings.applySettings(settingsKeys, settings); + } + + return true; +} + +int AaroniaRTSAInput::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int AaroniaRTSAInput::webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + MsgStartStop *message = MsgStartStop::create(run); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgStartStop *msgToGUI = MsgStartStop::create(run); + m_guiMessageQueue->push(msgToGUI); + } + + return 200; +} + +int AaroniaRTSAInput::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAaroniaRtsaSettings(new SWGSDRangel::SWGAaroniaRTSASettings()); + response.getAaroniaRtsaSettings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int AaroniaRTSAInput::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + AaroniaRTSAInputSettings settings = m_settings; + webapiUpdateDeviceSettings(settings, deviceSettingsKeys, response); + + MsgConfigureAaroniaRTSA *msg = MsgConfigureAaroniaRTSA::create(settings, deviceSettingsKeys, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureAaroniaRTSA *msgToGUI = MsgConfigureAaroniaRTSA::create(settings, deviceSettingsKeys, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +void AaroniaRTSAInput::webapiUpdateDeviceSettings( + AaroniaRTSAInputSettings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response) +{ + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getAaroniaRtsaSettings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_sampleRate = response.getAaroniaRtsaSettings()->getSampleRate(); + } + if (deviceSettingsKeys.contains("serverAddress")) { + settings.m_serverAddress = *response.getAaroniaRtsaSettings()->getServerAddress(); + } + if (deviceSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getAaroniaRtsaSettings()->getUseReverseApi() != 0; + } + if (deviceSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getAaroniaRtsaSettings()->getReverseApiAddress(); + } + if (deviceSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getAaroniaRtsaSettings()->getReverseApiPort(); + } + if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getAaroniaRtsaSettings()->getReverseApiDeviceIndex(); + } +} + +int AaroniaRTSAInput::webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAaroniaSdrReport(new SWGSDRangel::SWGAaroniaRTSAReport()); + response.getAirspyHfReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +void AaroniaRTSAInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const AaroniaRTSAInputSettings& settings) +{ + response.getAaroniaRtsaSettings()->setCenterFrequency(settings.m_centerFrequency); + response.getAaroniaRtsaSettings()->setSampleRate(settings.m_sampleRate); + + if (response.getAaroniaRtsaSettings()->getServerAddress()) { + *response.getAaroniaRtsaSettings()->getServerAddress() = settings.m_serverAddress; + } else { + response.getAaroniaRtsaSettings()->setServerAddress(new QString(settings.m_serverAddress)); + } + + response.getAaroniaRtsaSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getAaroniaRtsaSettings()->getReverseApiAddress()) { + *response.getAaroniaRtsaSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getAaroniaRtsaSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getAaroniaRtsaSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getAaroniaRtsaSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); +} + +void AaroniaRTSAInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + response.getAaroniaSdrReport()->setStatus(getStatus()); +} + +void AaroniaRTSAInput::webapiReverseSendSettings(const QList& deviceSettingsKeys, const AaroniaRTSAInputSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(0); // single Rx + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("AaroniaRTSA")); + swgDeviceSettings->setAaroniaRtsaSettings(new SWGSDRangel::SWGAaroniaRTSASettings()); + SWGSDRangel::SWGAaroniaRTSASettings *swgAaroniaRTSASettings = swgDeviceSettings->getAaroniaRtsaSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgAaroniaRTSASettings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("serverAddress") || force) { + swgAaroniaRTSASettings->setServerAddress(new QString(settings.m_serverAddress)); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->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 swgDeviceSettings; +} + +void AaroniaRTSAInput::webapiReverseSendStartStop(bool start) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(0); // single Rx + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("AaroniaRTSA")); + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + QNetworkReply *reply; + + if (start) { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer); + } else { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer); + } + + buffer->setParent(reply); + delete swgDeviceSettings; +} + +void AaroniaRTSAInput::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "AaroniaRTSAInput::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("AaroniaRTSAInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainput.h b/plugins/samplesource/aaroniartsainput/aaroniartsainput.h new file mode 100644 index 000000000..5dc05aa72 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainput.h @@ -0,0 +1,186 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _AARONIARTSA_AARONIARTSAINPUT_H_ +#define _AARONIARTSA_AARONIARTSAINPUT_H_ + +#include +#include +#include +#include + +#include +#include "aaroniartsainputsettings.h" + +class DeviceAPI; +class AaroniaRTSAInputWorker; +class QNetworkAccessManager; +class QNetworkReply; +class QThread; + +class AaroniaRTSAInput : public DeviceSampleSource { + Q_OBJECT +public: + class MsgConfigureAaroniaRTSA : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const AaroniaRTSAInputSettings& getSettings() const { return m_settings; } + const QList& getSettingsKeys() const { return m_settingsKeys; } + bool getForce() const { return m_force; } + + static MsgConfigureAaroniaRTSA* create(const AaroniaRTSAInputSettings& settings, const QList& settingsKeys, bool force) + { + return new MsgConfigureAaroniaRTSA(settings, settingsKeys, force); + } + + private: + AaroniaRTSAInputSettings m_settings; + QList m_settingsKeys; + bool m_force; + + MsgConfigureAaroniaRTSA(const AaroniaRTSAInputSettings& settings, const QList& settingsKeys, bool force) : + Message(), + m_settings(settings), + m_settingsKeys(settingsKeys), + m_force(force) + { } + }; + + 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) + { } + }; + + class MsgSetStatus : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getStatus() const { return m_status; } + + static MsgSetStatus* create(int status) { + return new MsgSetStatus(status); + } + + protected: + int m_status; + + MsgSetStatus(int status) : + Message(), + m_status(status) + { } + }; + + AaroniaRTSAInput(DeviceAPI *deviceAPI); + virtual ~AaroniaRTSAInput(); + virtual void destroy(); + + virtual void init(); + virtual bool start(); + virtual void stop(); + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + virtual const QString& getDeviceDescription() const; + virtual int getSampleRate() const; + virtual void setSampleRate(int sampleRate) { (void) sampleRate; } + virtual quint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + + virtual bool handleMessage(const Message& message); + + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + + virtual int webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage); + + static void webapiFormatDeviceSettings( + SWGSDRangel::SWGDeviceSettings& response, + const AaroniaRTSAInputSettings& settings); + + static void webapiUpdateDeviceSettings( + AaroniaRTSAInputSettings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response); + +private: + DeviceAPI *m_deviceAPI; + QMutex m_mutex; + int m_sampleRate; + quint64 m_centerFrequency; + AaroniaRTSAInputSettings m_settings; + AaroniaRTSAInputWorker* m_aaroniaRTSAWorker; + QThread *m_aaroniaRTSAWorkerThread; + QString m_deviceDescription; + bool m_running; + const QTimer& m_masterTimer; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + int getStatus() const; + bool applySettings(const AaroniaRTSAInputSettings& settings, const QList& settingsKeys, bool force); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiReverseSendSettings(const QList& deviceSettingsKeys, const AaroniaRTSAInputSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +signals: + void startWorker(); + void stopWorker(); + void setWorkerCenterFrequency(quint64 centerFrequency); + void setWorkerSampleRate(int sampleRate); + void setWorkerServerAddress(QString serverAddress); + +private slots: + void setWorkerStatus(int status); + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // _AARONIARTSA_AARONIARTSAINPUT_H_ diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.cpp new file mode 100644 index 000000000..c204ab44c --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.cpp @@ -0,0 +1,347 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include +#include +#include + +#include "ui_aaroniartsainputgui.h" +#include "plugin/pluginapi.h" +#include "gui/colormapper.h" +#include "gui/glspectrum.h" +#include "gui/basicdevicesettingsdialog.h" +#include "gui/dialogpositioner.h" +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "util/db.h" + +#include "mainwindow.h" + +#include "aaroniartsainputgui.h" +#include "device/deviceapi.h" +#include "device/deviceuiset.h" + +AaroniaRTSAInputGui::AaroniaRTSAInputGui(DeviceUISet *deviceUISet, QWidget* parent) : + DeviceGUI(parent), + ui(new Ui::AaroniaRTSAInputGui), + m_settings(), + m_doApplySettings(true), + m_forceSettings(true), + m_sampleSource(0), + m_tickCount(0), + m_lastEngineState(DeviceAPI::StNotStarted) +{ + qDebug("AaroniaRTSAInputGui::AaroniaRTSAInputGui"); + m_deviceUISet = deviceUISet; + setAttribute(Qt::WA_DeleteOnClose, true); + m_sampleSource = m_deviceUISet->m_deviceAPI->getSampleSource(); + + m_statusTooltips.push_back("Idle"); // 0 + m_statusTooltips.push_back("Unstable"); // 1 + m_statusTooltips.push_back("Connected"); // 2 + m_statusTooltips.push_back("Error"); // 3 + m_statusTooltips.push_back("Disconnected"); // 4 + + m_statusColors.push_back("gray"); // Idle + m_statusColors.push_back("rgb(232, 212, 35)"); // Unstable (yellow) + m_statusColors.push_back("rgb(35, 138, 35)"); // Connected (green) + m_statusColors.push_back("rgb(232, 85, 85)"); // Error (red) + m_statusColors.push_back("rgb(232, 85, 232)"); // Disconnected (magenta) + + ui->setupUi(getContents()); + sizeToContents(); + getContents()->setStyleSheet("#AaroniaRTSAInputGui { background-color: rgb(64, 64, 64); }"); + m_helpURL = "plugins/samplesource/aaroniartsainput/readme.md"; + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->centerFrequency->setValueRange(9, 0, 999999999); + + ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); + ui->sampleRate->setValueRange(8, 2000U, 20000000U); + + displaySettings(); + makeUIConnections(); + + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(500); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); + m_sampleSource->setMessageQueueToGUI(&m_inputMessageQueue); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); +} + +AaroniaRTSAInputGui::~AaroniaRTSAInputGui() +{ + delete ui; +} + +void AaroniaRTSAInputGui::destroy() +{ + delete this; +} + +void AaroniaRTSAInputGui::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + m_forceSettings = true; + sendSettings(); +} + +QByteArray AaroniaRTSAInputGui::serialize() const +{ + return m_settings.serialize(); +} + +bool AaroniaRTSAInputGui::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + m_forceSettings = true; + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +void AaroniaRTSAInputGui::on_startStop_toggled(bool checked) +{ + if (m_doApplySettings) + { + AaroniaRTSAInput::MsgStartStop *message = AaroniaRTSAInput::MsgStartStop::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); + } +} + +void AaroniaRTSAInputGui::on_centerFrequency_changed(quint64 value) +{ + m_settings.m_centerFrequency = value * 1000; + m_settingsKeys.append("centerFrequency"); + sendSettings(); +} + +void AaroniaRTSAInputGui::on_sampleRate_changed(quint64 value) +{ + m_settings.m_sampleRate = value; + m_settingsKeys.append("sampleRate"); + sendSettings(); +} + +void AaroniaRTSAInputGui::on_serverAddress_returnPressed() +{ + on_serverAddressApplyButton_clicked(); +} + +void AaroniaRTSAInputGui::on_serverAddressApplyButton_clicked() +{ + QString serverAddress = ui->serverAddress->text(); + QUrl url(serverAddress); + + if (QStringList{"ws", "wss", "http", "https"}.contains(url.scheme())) { + m_settings.m_serverAddress = QString("%1:%2").arg(url.host()).arg(url.port()); + } else { + m_settings.m_serverAddress = serverAddress; + } + + m_settingsKeys.append("serverAddress"); + sendSettings(); +} + +void AaroniaRTSAInputGui::displaySettings() +{ + blockApplySettings(true); + + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + ui->serverAddress->setText(m_settings.m_serverAddress); + + blockApplySettings(false); +} + +void AaroniaRTSAInputGui::sendSettings() +{ + if (!m_updateTimer.isActive()) { + m_updateTimer.start(100); + } +} + +void AaroniaRTSAInputGui::updateHardware() +{ + if (m_doApplySettings) + { + AaroniaRTSAInput::MsgConfigureAaroniaRTSA* message = AaroniaRTSAInput::MsgConfigureAaroniaRTSA::create(m_settings, m_settingsKeys, m_forceSettings); + m_sampleSource->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_settingsKeys.clear(); + m_updateTimer.stop(); + } +} + +void AaroniaRTSAInputGui::updateStatus() +{ + int state = m_deviceUISet->m_deviceAPI->state(); + + if (m_lastEngineState != state) + { + switch (state) + { + case DeviceAPI::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DeviceAPI::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DeviceAPI::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DeviceAPI::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } +} + +bool AaroniaRTSAInputGui::handleMessage(const Message& message) +{ + if (AaroniaRTSAInput::MsgConfigureAaroniaRTSA::match(message)) + { + qDebug("AaroniaRTSAInputGui::handleMessage: MsgConfigureAaroniaRTSA"); + const AaroniaRTSAInput::MsgConfigureAaroniaRTSA& cfg = (AaroniaRTSAInput::MsgConfigureAaroniaRTSA&) message; + + if (cfg.getForce()) { + m_settings = cfg.getSettings(); + } else { + m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings()); + } + + displaySettings(); + return true; + } + else if (AaroniaRTSAInput::MsgStartStop::match(message)) + { + qDebug("AaroniaRTSAInputGui::handleMessage: MsgStartStop"); + AaroniaRTSAInput::MsgStartStop& notif = (AaroniaRTSAInput::MsgStartStop&) message; + blockApplySettings(true); + ui->startStop->setChecked(notif.getStartStop()); + blockApplySettings(false); + + return true; + } + else if (AaroniaRTSAInput::MsgSetStatus::match(message)) + { + qDebug("AaroniaRTSAInputGui::handleMessage: MsgSetStatus"); + AaroniaRTSAInput::MsgSetStatus& notif = (AaroniaRTSAInput::MsgSetStatus&) message; + int status = notif.getStatus(); + ui->statusIndicator->setToolTip(m_statusTooltips[status]); + ui->statusIndicator->setStyleSheet("QLabel { background-color: " + + m_statusColors[status] + "; border-radius: 7px; }"); + return true; + } + else + { + return false; + } +} + +void AaroniaRTSAInputGui::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + if (DSPSignalNotification::match(*message)) + { + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_deviceSampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("AaroniaRTSAInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", + notif->getSampleRate(), + notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + + delete message; + } + else + { + if (handleMessage(*message)) + { + delete message; + } + } + } +} + +void AaroniaRTSAInputGui::updateSampleRateAndFrequency() +{ + m_deviceUISet->getSpectrum()->setSampleRate(m_deviceSampleRate); + m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + // ui->deviceRateText->setText(tr("%1M").arg((float)m_deviceSampleRate / 1000 / 1000)); + ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_deviceSampleRate / 1000.0f, 'g', 5))); + blockApplySettings(true); + ui->centerFrequency->setValue(m_deviceCenterFrequency / 1000); + ui->sampleRate->setValue(m_deviceSampleRate); + blockApplySettings(false); +} + +void AaroniaRTSAInputGui::openDeviceSettingsDialog(const QPoint& p) +{ + if (m_contextMenuType == ContextMenuDeviceSettings) + { + BasicDeviceSettingsDialog dialog(this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + + dialog.move(p); + new DialogPositioner(&dialog, false); + dialog.exec(); + + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settingsKeys.append("useReverseAPI"); + m_settingsKeys.append("reverseAPIAddress"); + m_settingsKeys.append("reverseAPIPort"); + m_settingsKeys.append("reverseAPIDeviceIndex"); + + sendSettings(); + } + + resetContextMenuType(); +} + +void AaroniaRTSAInputGui::makeUIConnections() +{ + QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &AaroniaRTSAInputGui::on_startStop_toggled); + QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &AaroniaRTSAInputGui::on_centerFrequency_changed); + QObject::connect(ui->sampleRate, &ValueDial::changed, this, &AaroniaRTSAInputGui::on_sampleRate_changed); + QObject::connect(ui->serverAddress, &QLineEdit::returnPressed, this, &AaroniaRTSAInputGui::on_serverAddress_returnPressed); + QObject::connect(ui->serverAddressApplyButton, &QPushButton::clicked, this, &AaroniaRTSAInputGui::on_serverAddressApplyButton_clicked); +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.h b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.h new file mode 100644 index 000000000..e523a6e85 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.h @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _AARONIARTSA_AARONIARTSAGUI_H_ +#define _AARONIARTSA_AARONIARTSAGUI_H_ + +#include +#include + +#include "device/devicegui.h" +#include "util/messagequeue.h" + +#include "aaroniartsainputsettings.h" +#include "aaroniartsainput.h" + +class DeviceUISet; + +namespace Ui { + class AaroniaRTSAInputGui; +} + +class AaroniaRTSAInputGui : public DeviceGUI { + Q_OBJECT + +public: + explicit AaroniaRTSAInputGui(DeviceUISet *deviceUISet, QWidget* parent = 0); + virtual ~AaroniaRTSAInputGui(); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +private: + Ui::AaroniaRTSAInputGui* ui; + + AaroniaRTSAInputSettings m_settings; + QList m_settingsKeys; + QTimer m_updateTimer; + QTimer m_statusTimer; + bool m_doApplySettings; + bool m_forceSettings; + DeviceSampleSource* m_sampleSource; + std::size_t m_tickCount; + int m_deviceSampleRate; + quint64 m_deviceCenterFrequency; //!< Center frequency in device + int m_lastEngineState; + MessageQueue m_inputMessageQueue; + std::vector m_statusColors; + std::vector m_statusTooltips; + + void blockApplySettings(bool block) { m_doApplySettings = !block; } + void displaySettings(); + void sendSettings(); + void updateSampleRateAndFrequency(); + bool handleMessage(const Message& message); + void makeUIConnections(); + +private slots: + void handleInputMessages(); + void on_startStop_toggled(bool checked); + void on_centerFrequency_changed(quint64 value); + void on_sampleRate_changed(quint64 value); + void on_serverAddress_returnPressed(); + void on_serverAddressApplyButton_clicked(); + void openDeviceSettingsDialog(const QPoint& p); + void updateStatus(); + void updateHardware(); +}; + +#endif // _AARONIARTSA_AARONIARTSAGUI_H_ diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.ui b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.ui new file mode 100644 index 000000000..15adc7968 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputgui.ui @@ -0,0 +1,326 @@ + + + AaroniaRTSAInputGui + + + + 0 + 0 + 360 + 131 + + + + + 0 + 0 + + + + + 360 + 130 + + + + + 380 + 131 + + + + + Liberation Sans + 9 + 50 + false + false + + + + AaroniaRTSA + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + + + + start/stop acquisition + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + + + + + + 58 + 0 + + + + I/Q sample rate kS/s + + + 0000.00k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 16 + 50 + false + false + + + + PointingHandCursor + + + Qt::StrongFocus + + + Tuner center frequency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + + + SR + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + false + + + + PointingHandCursor + + + Device sample rate + + + + + + + S/s + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Addr + + + + + + + Server address + + + 127.0.0.1:8073 + + + + + + + + 0 + 0 + + + + + 14 + 14 + + + + Idle + + + QLabel { background-color: gray; border-radius: 7px; } + + + + + + + + + + + 30 + 16777215 + + + + Set + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + + + +
diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.cpp new file mode 100644 index 000000000..a1bafcae7 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.cpp @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" + +#ifdef SERVER_MODE +#include "aaroniartsainput.h" +#else +#include "aaroniartsainputgui.h" +#endif +#include "aaroniartsainputplugin.h" +#include "aaroniartsainputwebapiadapter.h" + +const PluginDescriptor AaroniaRTSAInputPlugin::m_pluginDescriptor = { + QStringLiteral("AaroniaRTSA"), + QStringLiteral("AaroniaRTSA input"), + QStringLiteral("7.12.0"), + QStringLiteral("(c) Edouard Griffiths, F4EXB"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +static constexpr const char* const m_hardwareID = "AaroniaRTSA"; +static constexpr const char* const m_deviceTypeID = AARONIARTSA_DEVICE_TYPE_ID; + +AaroniaRTSAInputPlugin::AaroniaRTSAInputPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& AaroniaRTSAInputPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void AaroniaRTSAInputPlugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleSource(m_deviceTypeID, this); +} + +void AaroniaRTSAInputPlugin::enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices) +{ + if (listedHwIds.contains(m_hardwareID)) { // check if it was done + return; + } + + originDevices.append(OriginDevice( + "AaroniaRTSA", + m_hardwareID, + QString(), + 0, + 1, // nb Rx + 0 // nb Tx + )); + + listedHwIds.append(m_hardwareID); +} + +PluginInterface::SamplingDevices AaroniaRTSAInputPlugin::enumSampleSources(const OriginDevices& originDevices) +{ + SamplingDevices result; + + for (OriginDevices::const_iterator it = originDevices.begin(); it != originDevices.end(); ++it) + { + if (it->hardwareId == m_hardwareID) + { + result.append(SamplingDevice( + it->displayableName, + m_hardwareID, + m_deviceTypeID, + it->serial, + it->sequence, + PluginInterface::SamplingDevice::BuiltInDevice, + PluginInterface::SamplingDevice::StreamSingleRx, + 1, + 0 + )); + } + } + + return result; +} + +#ifdef SERVER_MODE +DeviceGUI* AaroniaRTSAInputPlugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + (void) sourceId; + (void) widget; + (void) deviceUISet; + return 0; +} +#else +DeviceGUI* AaroniaRTSAInputPlugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if(sourceId == m_deviceTypeID) { + AaroniaRTSAInputGui* gui = new AaroniaRTSAInputGui(deviceUISet); + *widget = gui; + return gui; + } else { + return 0; + } +} +#endif + +DeviceSampleSource *AaroniaRTSAInputPlugin::createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI) +{ + if (sourceId == m_deviceTypeID) + { + AaroniaRTSAInput* input = new AaroniaRTSAInput(deviceAPI); + return input; + } + else + { + return 0; + } +} + +DeviceWebAPIAdapter *AaroniaRTSAInputPlugin::createDeviceWebAPIAdapter() const +{ + return new AaroniaRTSAInputWebAPIAdapter(); +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.h b/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.h new file mode 100644 index 000000000..13ab5d3fa --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputplugin.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _AARONIARTSA_AARONIARTSAPLUGIN_H +#define _AARONIARTSA_AARONIARTSAPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; + +#define AARONIARTSA_DEVICE_TYPE_ID "sdrangel.samplesource.aaroniartsasource" + +class AaroniaRTSAInputPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID AARONIARTSA_DEVICE_TYPE_ID) + +public: + explicit AaroniaRTSAInputPlugin(QObject* parent = NULL); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices); + virtual SamplingDevices enumSampleSources(const OriginDevices& originDevices); + virtual DeviceGUI* createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet); + virtual DeviceSampleSource* createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI); + virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; +}; + +#endif // _AARONIARTSA_AARONIARTSAPLUGIN_H diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.cpp new file mode 100644 index 000000000..8a8937945 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.cpp @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "util/simpleserializer.h" +#include "aaroniartsainputsettings.h" + +AaroniaRTSAInputSettings::AaroniaRTSAInputSettings() +{ + resetToDefaults(); +} + +void AaroniaRTSAInputSettings::resetToDefaults() +{ + m_centerFrequency = 1450000; + m_sampleRate = 200000; + m_serverAddress = "127.0.0.1:8073"; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; +} + +QByteArray AaroniaRTSAInputSettings::serialize() const +{ + SimpleSerializer s(2); + + s.writeString(2, m_serverAddress); + s.writeS32(3, m_sampleRate); + s.writeBool(100, m_useReverseAPI); + s.writeString(101, m_reverseAPIAddress); + s.writeU32(102, m_reverseAPIPort); + s.writeU32(103, m_reverseAPIDeviceIndex); + + return s.final(); +} + +bool AaroniaRTSAInputSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 2) + { + uint32_t utmp; + + d.readString(2, &m_serverAddress, "127.0.0.1:8073"); + d.readS32(3, &m_sampleRate, 200000); + d.readBool(100, &m_useReverseAPI, false); + d.readString(101, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(102, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } + else { + m_reverseAPIPort = 8888; + } + + d.readU32(103, &utmp, 0); + m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +void AaroniaRTSAInputSettings::applySettings(const QStringList& settingsKeys, const AaroniaRTSAInputSettings& settings) +{ + if (settingsKeys.contains("centerFrequency")) { + m_centerFrequency = settings.m_centerFrequency; + } + if (settingsKeys.contains("sampleRate")) { + m_sampleRate = settings.m_sampleRate; + } + if (settingsKeys.contains("serverAddress")) { + m_serverAddress = settings.m_serverAddress; + } + if (settingsKeys.contains("useReverseAPI")) { + m_useReverseAPI = settings.m_useReverseAPI; + } + if (settingsKeys.contains("reverseAPIAddress")) { + m_reverseAPIAddress = settings.m_reverseAPIAddress; + } + if (settingsKeys.contains("reverseAPIPort")) { + m_reverseAPIPort = settings.m_reverseAPIPort; + } + if (settingsKeys.contains("reverseAPIDeviceIndex")) { + m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex; + } +} + +QString AaroniaRTSAInputSettings::getDebugString(const QStringList& settingsKeys, bool force) const +{ + std::ostringstream ostr; + + if (settingsKeys.contains("centerFrequency") || force) { + ostr << " m_centerFrequency: " << m_centerFrequency; + } + if (settingsKeys.contains("sampleRate") || force) { + ostr << " m_sampleRate: " << m_sampleRate; + } + if (settingsKeys.contains("serverAddress") || force) { + ostr << " m_serverAddress: " << m_serverAddress.toStdString(); + } + if (settingsKeys.contains("useReverseAPI") || force) { + ostr << " m_useReverseAPI: " << m_useReverseAPI; + } + if (settingsKeys.contains("reverseAPIAddress") || force) { + ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString(); + } + if (settingsKeys.contains("reverseAPIPort") || force) { + ostr << " m_reverseAPIPort: " << m_reverseAPIPort; + } + if (settingsKeys.contains("reverseAPIDeviceIndex") || force) { + ostr << " m_reverseAPIDeviceIndex: " << m_reverseAPIDeviceIndex; + } + + return QString(ostr.str().c_str()); +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.h b/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.h new file mode 100644 index 000000000..122a33147 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputsettings.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _AARONIARTSA_AARONIARTSASETTINGS_H_ +#define _AARONIARTSA_AARONIARTSASETTINGS_H_ + +#include +#include + +struct AaroniaRTSAInputSettings { + + enum ConnectionStatus + { + ConnectionIdle, // 0 - gray + ConnectionUnstable, // 1 - yellow + ConnectionOK, // 2 - green + ConnectionError, // 3 - red + ConnectionDisconnected // 4 - magenta + }; + + quint64 m_centerFrequency; + int m_sampleRate; + QString m_serverAddress; + + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + + AaroniaRTSAInputSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + void applySettings(const QStringList& settingsKeys, const AaroniaRTSAInputSettings& settings); + QString getDebugString(const QStringList& settingsKeys, bool force=false) const; +}; + +#endif /* _AARONIARTSA_AARONIARTSASETTINGS_H_ */ diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.cpp new file mode 100644 index 000000000..2a71e593d --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.cpp @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGDeviceSettings.h" +#include "aaroniartsainput.h" +#include "aaroniartsainputwebapiadapter.h" + +AaroniaRTSAInputWebAPIAdapter::AaroniaRTSAInputWebAPIAdapter() +{} + +AaroniaRTSAInputWebAPIAdapter::~AaroniaRTSAInputWebAPIAdapter() +{} + +int AaroniaRTSAInputWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setAaroniaRtsaSettings(new SWGSDRangel::SWGAaroniaRTSASettings()); + response.getAaroniaRtsaSettings()->init(); + AaroniaRTSAInput::webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int AaroniaRTSAInputWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) force; // no action + (void) errorMessage; + AaroniaRTSAInput::webapiUpdateDeviceSettings(m_settings, deviceSettingsKeys, response); + return 200; +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.h b/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.h new file mode 100644 index 000000000..c97148886 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputwebapiadapter.h @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "device/devicewebapiadapter.h" +#include "aaroniartsainputsettings.h" + +class AaroniaRTSAInputWebAPIAdapter : public DeviceWebAPIAdapter +{ +public: + AaroniaRTSAInputWebAPIAdapter(); + virtual ~AaroniaRTSAInputWebAPIAdapter(); + virtual QByteArray serialize() { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + +private: + AaroniaRTSAInputSettings m_settings; +}; diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.cpp b/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.cpp new file mode 100644 index 000000000..b0f6f40b5 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.cpp @@ -0,0 +1,422 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +#include "util/messagequeue.h" +#include "dsp/dspcommands.h" + +#include "aaroniartsainputsettings.h" +#include "aaroniartsainputworker.h" + +MESSAGE_CLASS_DEFINITION(AaroniaRTSAInputWorker::MsgReportSampleRateAndFrequency, Message) + +AaroniaRTSAInputWorker::AaroniaRTSAInputWorker(SampleSinkFifo* sampleFifo) : + QObject(), + m_timer(this), + m_samplesBuf(), + m_sampleFifo(sampleFifo), + m_centerFrequency(0), + m_sampleRate(1), + m_inputMessageQueue(nullptr), + m_status(AaroniaRTSAInputSettings::ConnectionIdle), + mReply(nullptr), + m_convertBuffer(64e6) +{ + // Initialize network managers + m_networkAccessManager = new QNetworkAccessManager(this); + m_networkAccessManagerConfig = new QNetworkAccessManager(this); + QObject::connect( + m_networkAccessManagerConfig, + &QNetworkAccessManager::finished, + this, + &AaroniaRTSAInputWorker::handleConfigReply + ); + + // Request 16bit raw samples + // m_serverAddress = "localhost:55123"; + // QUrl url(tr("http://%1/stream?format=float32").arg(m_serverAddress)); + + // QNetworkRequest req(url); + // mReply = m_networkAccessManager->get(req); + + // // Connect Qt slots to network events + // connect(mReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError))); + // connect(mReply, SIGNAL(finished()), this, SLOT(onFinished())); + // connect(mReply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); + + mPrevTime = 0; + mPacketSamples = 0; +} + +AaroniaRTSAInputWorker::~AaroniaRTSAInputWorker() +{ + if (mReply) + { + // disconnect previous sugnals + disconnect(mReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError))); + disconnect(mReply, SIGNAL(finished()), this, SLOT(onFinished())); + disconnect(mReply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); + + mReply->abort(); + mReply->deleteLater(); + } + + m_networkAccessManager->deleteLater(); + + QObject::disconnect( + m_networkAccessManagerConfig, + &QNetworkAccessManager::finished, + this, + &AaroniaRTSAInputWorker::handleConfigReply + ); + m_networkAccessManagerConfig->deleteLater(); +} + +void AaroniaRTSAInputWorker::onSocketError(QAbstractSocket::SocketError error) +{ + (void) error; + m_status = AaroniaRTSAInputSettings::ConnectionError; + emit updateStatus(m_status); +} + +void AaroniaRTSAInputWorker::sendCenterFrequencyAndSampleRate() +{ + if (m_iqDemodName.size() == 0) { + return; + } + + qDebug("AaroniaRTSAInputWorker::sendCenterFrequencyAndSampleRate: %llu samplerate: %d", m_centerFrequency, m_sampleRate); + + QJsonObject object { + {"receiverName", m_iqDemodName}, + {"simpleconfig", QJsonObject({ + {"main", QJsonObject({ + {"centerfreq", QJsonValue((qint64) m_centerFrequency)}, + {"samplerate", QJsonValue(m_sampleRate)}, + {"spanfreq", QJsonValue(m_sampleRate)}, + })} + })} + }; + + QJsonDocument document; + document.setObject(object); + QUrl url(tr("http://%1/remoteconfig").arg(m_serverAddress)); + QNetworkRequest request(url); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + m_networkAccessManagerConfig->put(request, document.toJson()); +} + +void AaroniaRTSAInputWorker::getConfig() +{ + QUrl url(tr("http://%1/remoteconfig").arg(m_serverAddress)); + QNetworkRequest request(url); + m_networkAccessManagerConfig->get(request); +} + +void AaroniaRTSAInputWorker::onCenterFrequencyChanged(quint64 centerFrequency) +{ + if (m_centerFrequency == centerFrequency) { + return; + } + + m_centerFrequency = centerFrequency; + sendCenterFrequencyAndSampleRate(); +} + +void AaroniaRTSAInputWorker::onSampleRateChanged(int sampleRate) +{ + if (m_sampleRate == sampleRate) { + return; + } + + m_sampleRate = sampleRate; + sendCenterFrequencyAndSampleRate(); +} + +void AaroniaRTSAInputWorker::onServerAddressChanged(QString serverAddress) +{ + m_status = AaroniaRTSAInputSettings::ConnectionDisconnected; + updateStatus(m_status); + + if (mReply) + { + // disconnect previous sugnals + disconnect(mReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError))); + disconnect(mReply, SIGNAL(finished()), this, SLOT(onFinished())); + disconnect(mReply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); + + mReply->abort(); + mReply->deleteLater(); + } + + QUrl url(tr("http://%1/stream?format=float32").arg(serverAddress)); + QNetworkRequest req(url); + mReply = m_networkAccessManager->get(req); + + // Connect Qt slots to network events + connect(mReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError))); + connect(mReply, SIGNAL(finished()), this, SLOT(onFinished())); + connect(mReply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); + + mPrevTime = 0; + mPacketSamples = 0; + m_serverAddress = serverAddress; + + getConfig(); +} + +void AaroniaRTSAInputWorker::tick() +{ +} + +/**************************CPY ********************************* */ + +void AaroniaRTSAInputWorker::onError(QNetworkReply::NetworkError code) +{ + (void) code; + qWarning() << "AaroniaRTSAInputWorker::onError: network Error: " << mReply->errorString(); + m_status = 3; + emit updateStatus(3); +} + +void AaroniaRTSAInputWorker::onFinished() +{ + qDebug() << "AaroniaRTSAInputWorker::onFinished(: finished: " << mReply->errorString(); + mBuffer.append(mReply->readAll()); + mReply->deleteLater(); + mReply = nullptr; +} + +// bytes received from the socket +void AaroniaRTSAInputWorker::onReadyRead() +{ + if (m_status != AaroniaRTSAInputSettings::ConnectionOK) + { + m_status = AaroniaRTSAInputSettings::ConnectionOK; + emit updateStatus(m_status); + } + + // read as many bytes as possible into input buffer + qint64 n = mReply->bytesAvailable(); + qint64 bs = mBuffer.size(); + mBuffer.resize(bs + n); + qint64 done = mReply->read(mBuffer.data() + bs, n); + mBuffer.resize(bs + done); + + // intialize parsing + int offset = 0; + int avail = mBuffer.size(); + + // consume all input data if possible + while (offset < avail) + { + // any samples so far (not looking for meta data) + if (mPacketSamples) + { + // enough samples + if (offset + mPacketSamples * 2 * sizeof(float) <= (unsigned long) avail) + { + // do something with the IQ data + const float *sp = (const float *)(mBuffer.constData() + offset); + + SampleVector::iterator it = m_convertBuffer.begin(); + + m_decimatorsFloatIQ.decimate1(&it, sp, 2*mPacketSamples); + + /*m_samplesBuf.clear(); + for (int i = 0; i < mPacketSamples*2; i+=2) + { + m_samplesBuf.push_back(Sample( + sp[i] << (SDR_RX_SAMP_SZ - 8), + sp[i+1] << (SDR_RX_SAMP_SZ - 8) + )); + }*/ + + //m_sampleFifo->write(m_samplesBuf.begin(), m_samplesBuf.end()); + m_sampleFifo->write(m_convertBuffer.begin(), it); + + //qDebug() << "IQ " << sp[0] << ", " << sp[1]; + //m_sampleFifo->write() + + // consume all samples from the input buffer + offset += mPacketSamples * 2 * sizeof(float); + mPacketSamples = 0; + } + else + { + break; + } + } + else + { + // is there a complete JSON metadata object in the buffer + int split = mBuffer.indexOf('\x1e', offset); + + if (split != -1) + { + // Extract it + QByteArray data = mBuffer.mid(offset, split - offset); + offset = split + 1; + + // Parse the JSON data + + QJsonParseError error; + QJsonDocument jdoc = QJsonDocument::fromJson(data, &error); + + if (error.error == QJsonParseError::NoError) + { + // Extract fields of interest + // double startTime = jdoc["startTime"].toDouble(), endTime = jdoc["endTime"].toDouble(); + int samples = jdoc["samples"].toInt(); + + // Dump packet loss + // if (startTime != mPrevTime) + // { + // qDebug() << "AaroniaRTSAInputWorker::onReadyRead: packet loss: " + // << QDateTime::fromMSecsSinceEpoch(startTime * 1000).toString() + // << " D " << endTime - startTime + // << " O " << startTime - mPrevTime + // << " S " << samples + // << " L " << QDateTime::currentMSecsSinceEpoch() / 1000.0 - startTime; + + // if (m_status != AaroniaRTSAInputSettings::ConnectionUnstable) + // { + // m_status = AaroniaRTSAInputSettings::ConnectionUnstable; + // emit updateStatus(m_status); + // } + // } + + // Switch to data phase + // mPrevTime = endTime; + mPacketSamples = samples; + // qDebug() << jdoc.toJson(); + quint64 endFreq = jdoc["endFrequency"].toDouble(); + quint64 startFreq = jdoc["startFrequency"].toDouble(); + int bw = endFreq - startFreq; + quint64 midFreq = (endFreq + startFreq) / 2; + + if ((bw != m_sampleRate) || (midFreq != m_centerFrequency)) + { + if (m_inputMessageQueue) + { + MsgReportSampleRateAndFrequency *msg = MsgReportSampleRateAndFrequency::create(bw, midFreq); + m_inputMessageQueue->push(msg); + } + + } + + m_sampleRate = bw; + m_centerFrequency = midFreq; + } + else + { + QTextStream qerr(stderr); + qerr << "Json Parse Error: " + error.errorString(); + } + } + else + { + break; + } + } + } + + // Remove consumed data from the buffer + mBuffer.remove(0, offset); +} + +void AaroniaRTSAInputWorker::handleConfigReply(QNetworkReply* reply) +{ + if (reply->operation() == QNetworkAccessManager::GetOperation) // return from GET to /remoteconfig + { + parseConfig(reply->readAll()); + } + else if (reply->operation() == QNetworkAccessManager::PutOperation) // return from PUT to /remoteconfig + { + int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if ((httpStatusCode / 100) == 2) { + qDebug("AaroniaRTSAInputWorker::handleConfigReply: remoteconfig OK (%d)", httpStatusCode); + } else { + qWarning("AaroniaRTSAInputWorker::handleConfigReply: remoteconfig ended with error (%d)", httpStatusCode); + } + } + + reply->deleteLater(); +} + +void AaroniaRTSAInputWorker::parseConfig(QByteArray bytes) +{ + QJsonDocument document = QJsonDocument::fromJson(bytes); + m_iqDemodName = ""; + + if (document.isObject()) + { + QJsonObject documentObject = document.object(); + + if (documentObject.contains(QStringLiteral("config"))) + { + QJsonObject config = documentObject.value(QStringLiteral("config")).toObject(); + + if (config.contains(QStringLiteral("items"))) + { + QJsonArray configItems = config.value(QStringLiteral("items")).toArray(); + + for (const auto& configIem : configItems) + { + QJsonObject configIemObject = configIem.toObject(); + + if (configIemObject.contains(QStringLiteral("name"))) + { + QString nameItem = configIemObject.value(QStringLiteral("name")).toString(); + + if (nameItem.startsWith("Block_IQDemodulator")) + { + m_iqDemodName = nameItem; + break; + } + } + } + } + else + { + qDebug() << "AaroniaRTSAInputWorker::parseConfig: config has no items: " << config; + } + + } + else + { + qDebug() << "AaroniaRTSAInputWorker::parseConfig: document has no config obhect: " << documentObject; + } + + } + else + { + qDebug() << "AaroniaRTSAInputWorker::parseConfig: Document is not an object: " << document; + } + + if (m_iqDemodName == "") { + qWarning("AaroniaRTSAInputWorker.parseConfig: could not find IQ demdulator"); + } else { + qDebug("AaroniaRTSAInputWorker::parseConfig: IQ demdulator name: %s", qPrintable(m_iqDemodName)); + } +} diff --git a/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.h b/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.h new file mode 100644 index 000000000..24109f067 --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/aaroniartsainputworker.h @@ -0,0 +1,123 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2023 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _AARONIARTSA_AARONIARTSAWORKER_H_ +#define _AARONIARTSA_AARONIARTSAWORKER_H_ + +#include + +#include "dsp/samplesinkfifo.h" +#include "util/message.h" + + +#include +#include +#include +#include +#include +#include +#include "dsp/decimatorsfi.h" + + + +class MessageQueue; + +class AaroniaRTSAInputWorker : public QObject { + Q_OBJECT + +public: + class MsgReportSampleRateAndFrequency : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + quint64 getCenterFrequency() const { return m_centerFrequency; } + + static MsgReportSampleRateAndFrequency* create(int sampleRate, quint64 centerFrequency) { + return new MsgReportSampleRateAndFrequency(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + quint64 m_centerFrequency; + + MsgReportSampleRateAndFrequency(int sampleRate, qint64 centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + + AaroniaRTSAInputWorker(SampleSinkFifo* sampleFifo); + ~AaroniaRTSAInputWorker(); + int getStatus() const { return m_status; } + void setInputMessageQueue(MessageQueue *messageQueue) { m_inputMessageQueue = messageQueue; } + +private: + QTimer m_timer; + + SampleVector m_samplesBuf; + SampleSinkFifo* m_sampleFifo; + + QString m_serverAddress; + quint64 m_centerFrequency; + int m_sampleRate; + MessageQueue *m_inputMessageQueue; + + int m_status; //!< See GUI for status number detail + + void sendCenterFrequencyAndSampleRate(); + void getConfig(); + void parseConfig(QByteArray bytes); + + // QT htttp clients + QNetworkAccessManager *m_networkAccessManager; + QNetworkAccessManager *m_networkAccessManagerConfig; + // Reply from the HTTP server + QNetworkReply *mReply; + // Input buffer + QByteArray mBuffer; + // Number of IQ sample pairs in the current packet + int mPacketSamples; + // Previous sample end time to check for packet loss + double mPrevTime; + // Current iQ demodulator name + QString m_iqDemodName; + //Decimators m_decimatorsIQ; + DecimatorsFI m_decimatorsFloatIQ; + SampleVector m_convertBuffer; + //void workIQ(unsigned int n_items); + + +signals: + void updateStatus(int status); + +public slots: + void onCenterFrequencyChanged(quint64 centerFrequency); + void onSampleRateChanged(int sampleRate); + void onServerAddressChanged(QString serverAddress); + +private slots: + void onSocketError(QAbstractSocket::SocketError error); + void onError(QNetworkReply::NetworkError code); + void onFinished(void); + void onReadyRead(void); + void handleConfigReply(QNetworkReply* reply); + void tick(); +}; + +#endif // _AARONIARTSA_AARONIARTSAWORKER_H_ diff --git a/plugins/samplesource/aaroniartsainput/readme.md b/plugins/samplesource/aaroniartsainput/readme.md new file mode 100644 index 000000000..0dad2b71f --- /dev/null +++ b/plugins/samplesource/aaroniartsainput/readme.md @@ -0,0 +1,66 @@ +

AaroniaRTSA input plugin

+ +

Introduction

+ +You can use this plugin to interface with a http server block in the Aaronia RTSA suite connected to a Spectran V6 device. It is assumed that you have prior knowledge of the Aaronia RTSA suite software and operation of the Spectran V6 RTSA (Real Time Spectrum Analyzer). However in this context there are some specificities i.e. it assumes that the "mission" (in RTSA suite terms) that is the equivalent of a "configuration" in SDRangel has a `HTTP Server` block preceded by a `IQ Demodulator` block (the equivalent of the "Frequency translating FIR filter" in GNU radio). The center frequency and span (equal to decimated sample rate) can be controlled from either RTSA sutie or SDRangel. + +An example flow graph could be the following (with two http servers) hence two possible Aaronia receivers in SDRangel: + +![Aaronia RTSA dual server](../../../doc/img/AaroniaRTSAInput_mission.png) + +On SDRangel side two instances of the plugin can listen to each one of the servers: + +![Aaronia RTSA dual server](../../../doc/img/AaroniaRTSAInput_sdrangel.png) + +Of course the `IQ Demodulator` span should fit in the bandwidth set in the Spectran V6 block else it will yield no output. + +You can obviously run the RTSA suite and SDRangel on the same machine and connect via localhost but there are advantages on a split setup: + + - The workload can be split between RTSA suite and SDRangel on two different machines. RTSA suite has to ingurgitate data from the Spectran and process it at a very high sample rate so this is demanding on CPU and latency. Often it is better to run it on its own dedicated machine. + + - You can have the RTSA suite run on a machine close to the Spectran. This is in fact mandatory due to the length of the USB cables. And you can run SDRangel on another machine (possibly quite more lightweight) anywhere on the network. You can also multiply the client machines running SDRangel. + +

Interface

+ +![Aaronia RTSA dual server](../../../doc/img/AaroniaRTSAInput.png) + +The top and bottom bars of the device window are described [here](../../../sdrgui/device/readme.md) + +

1: Start/Stop

+ +This button is used to start the "device" i.e connect to the remote and start stream or stop the "device" i.e. stop stream and disconnect from the remote. The button shows the following faces: + + - Blue triangle icon: device is ready and can be started + - Green square icon: device is running and can be stopped + +

2: Stream sample rate

+ +This is the stream sample rate in S/s with multiplier. It should be equal to what is displayed in (4). + +

3: Frequency

+ +This is the center frequency received in he stream meta data. When setting it it will try to set the center frequency of the `IQ Demodulator` in RTSA suite the closest to the `HTTP server`. + +

4: Stream sample rate

+ +This is sample rate (actually the frequency span) received in the stream meta data. When setting it it will try to set the sample rate and frequency span of the IQ Demodulator` in RTSA suite the closest to the `HTTP server`. + +

5: Remote address and port

+ +This is the remote address and port of the `HTTP server` block in RTSA suite. The address has to be in the form of an IPv4 address. + +Press button (7) to validate your change. + +

6: Status indicator

+ +This ball can take the following colors depending on the status: + + - **Gray**: Idle + - **Yellow**: Unstable + - **Green**: Connected + - **Red**: Error + - **Magenta**: Disconnected + +

7: Set address

+ +When you change the address in (5) you have to push this button to validate the change. diff --git a/plugins/samplesource/airspy/airspygui.cpp b/plugins/samplesource/airspy/airspygui.cpp index 06e208fd5..9cb1b9364 100644 --- a/plugins/samplesource/airspy/airspygui.cpp +++ b/plugins/samplesource/airspy/airspygui.cpp @@ -399,8 +399,8 @@ void AirspyGui::on_transverter_clicked() updateFrequencyLimits(); m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; m_settingsKeys.append("transverterMode"); - m_settingsKeys.append("m_transverterDeltaFrequency"); - m_settingsKeys.append("m_iqOrder"); + m_settingsKeys.append("transverterDeltaFrequency"); + m_settingsKeys.append("iqOrder"); m_settingsKeys.append("centerFrequency"); sendSettings(); } diff --git a/plugins/samplesource/sdrplay/sdrplaythread.h b/plugins/samplesource/sdrplay/sdrplaythread.h index dcb00d9ba..2c645d7c6 100644 --- a/plugins/samplesource/sdrplay/sdrplaythread.h +++ b/plugins/samplesource/sdrplay/sdrplaythread.h @@ -55,7 +55,7 @@ private: int m_fcPos; bool m_iqOrder; - Decimators m_decimatorsIQ; + Decimators m_decimatorsIQ; Decimators m_decimatorsQI; void run(); diff --git a/sdrbase/resources/webapi.qrc b/sdrbase/resources/webapi.qrc index dcd4072d4..51bfa37fa 100644 --- a/sdrbase/resources/webapi.qrc +++ b/sdrbase/resources/webapi.qrc @@ -2,6 +2,7 @@ webapi/doc/html2/index.html webapi/doc/swagger/swagger.yaml + webapi/doc/swagger/include/AaroniaRTSA.yaml webapi/doc/swagger/include/ADSBDemod.yaml webapi/doc/swagger/include/AFC.yaml webapi/doc/swagger/include/Airspy.yaml diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index a9de3b3cf..1ba852b64 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -2097,6 +2097,46 @@ margin-bottom: 20px; } }, "description" : "ATVMod" +}; + defs.AaroniaRTSAReport = { + "properties" : { + "status" : { + "type" : "integer", + "description" : "0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected" + } + }, + "description" : "AaroniaRTSA" +}; + defs.AaroniaRTSASettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64", + "description" : "Sets the center frequency (Hz) of the distant IQ demodulator" + }, + "sampleRate" : { + "type" : "integer", + "description" : "Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator" + }, + "serverAddress" : { + "type" : "string", + "description" : "Distant AaroniaRTSA instance URL or IPv4 address with port" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + } + }, + "description" : "AaroniaRTSA" }; defs.AirspyHFReport = { "properties" : { @@ -3538,9 +3578,6 @@ margin-bottom: 20px; "HeatMapReport" : { "$ref" : "#/definitions/HeatMapReport" }, - "ILSDemodReport" : { - "$ref" : "#/definitions/ILSDemodReport" - }, "M17DemodReport" : { "$ref" : "#/definitions/M17DemodReport" }, @@ -3705,9 +3742,6 @@ margin-bottom: 20px; "HeatMapSettings" : { "$ref" : "#/definitions/HeatMapSettings" }, - "ILSDemodSettings" : { - "$ref" : "#/definitions/ILSDemodSettings" - }, "InterferometerSettings" : { "$ref" : "#/definitions/InterferometerSettings" }, @@ -5205,6 +5239,9 @@ margin-bottom: 20px; }, "xtrxMIMOReport" : { "$ref" : "#/definitions/XtrxMIMOReport" + }, + "aaroniaSDRReport" : { + "$ref" : "#/definitions/AaroniaRTSAReport" } }, "description" : "Base device report. Only the device report corresponding to the device specified in the deviceHwType is or should be present." @@ -5393,6 +5430,9 @@ margin-bottom: 20px; }, "xtrxMIMOSettings" : { "$ref" : "#/definitions/XtrxMIMOSettings" + }, + "aaroniaRTSASettings" : { + "$ref" : "#/definitions/AaroniaRTSASettings" } }, "description" : "Base device settings. Only the device settings corresponding to the device specified in the deviceHwType field is or should be present." @@ -7413,143 +7453,6 @@ margin-bottom: 20px; } }, "description" : "IEEE_802_15_4_Mod" -}; - defs.ILSDemodReport = { - "properties" : { - "channelPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "power received in channel (dB)" - }, - "channelSampleRate" : { - "type" : "integer" - } - }, - "description" : "ILSDemod" -}; - defs.ILSDemodSettings = { - "properties" : { - "inputFrequencyOffset" : { - "type" : "integer", - "format" : "int64" - }, - "rfBandwidth" : { - "type" : "number", - "format" : "float" - }, - "mode" : { - "type" : "integer", - "description" : "(0 for LOC, 1 for G/S)" - }, - "frequencyIndex" : { - "type" : "integer" - }, - "squelch" : { - "type" : "integer" - }, - "volume" : { - "type" : "number", - "format" : "float" - }, - "audioMute" : { - "type" : "integer" - }, - "average" : { - "type" : "integer" - }, - "ddmUnits" : { - "type" : "integer" - }, - "identThreshold" : { - "type" : "number", - "format" : "float" - }, - "ident" : { - "type" : "string" - }, - "runway" : { - "type" : "string" - }, - "trueBearing" : { - "type" : "number", - "format" : "float" - }, - "latitude" : { - "type" : "string" - }, - "longitude" : { - "type" : "string" - }, - "elevation" : { - "type" : "integer" - }, - "glidePath" : { - "type" : "number", - "format" : "float" - }, - "refHeight" : { - "type" : "number", - "format" : "float" - }, - "courseWidth" : { - "type" : "number", - "format" : "float" - }, - "udpEnabled" : { - "type" : "integer", - "description" : "Whether to forward DDM to specified UDP port" - }, - "udpAddress" : { - "type" : "string", - "description" : "UDP address to forward DDM to" - }, - "udpPort" : { - "type" : "integer", - "description" : "UDP port to forward DDM to" - }, - "logFilename" : { - "type" : "string" - }, - "logEnabled" : { - "type" : "integer" - }, - "rgbColor" : { - "type" : "integer" - }, - "title" : { - "type" : "string" - }, - "streamIndex" : { - "type" : "integer", - "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." - }, - "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" - }, - "scopeConfig" : { - "$ref" : "#/definitions/GLScope" - }, - "channelMarker" : { - "$ref" : "#/definitions/ChannelMarker" - }, - "rollupState" : { - "$ref" : "#/definitions/RollupState" - } - }, - "description" : "ILSDemod" }; defs.InstanceChannelsResponse = { "required" : [ "channelcount" ], @@ -9209,7 +9112,7 @@ margin-bottom: 20px; }, "altitudeReference" : { "type" : "integer", - "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND." + "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND" }, "animations" : { "type" : "array", @@ -9258,14 +9161,6 @@ margin-bottom: 20px; "availableUntil" : { "type" : "string", "description" : "Date and time until after which this item should no longer appear on 3D map" - }, - "colorValid" : { - "type" : "integer", - "description" : "0 - Use default color, 1 - Use specified color" - }, - "color" : { - "type" : "integer", - "description" : "RGBA for polygon and polyline" } }, "description" : "An item to draw on the map. Set image to an empty string to remove item from the map." @@ -9368,7 +9263,7 @@ margin-bottom: 20px; }, "altitudeReference" : { "type" : "integer", - "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND." + "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND" }, "animations" : { "type" : "array", @@ -9417,14 +9312,6 @@ margin-bottom: 20px; "availableUntil" : { "type" : "string", "description" : "Date and time until after which this item should no longer appear on 3D map" - }, - "colorValid" : { - "type" : "integer", - "description" : "0 - Use default color, 1 - Use specified color" - }, - "color" : { - "type" : "integer", - "description" : "RGBA for polygon and polyline" } }, "description" : "An item to draw on the map. Set image to an empty string to remove item from the map." @@ -9444,10 +9331,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "Display object names on the map (1 for yes, 0 for no)" }, - "terrain" : { - "type" : "string", - "description" : "Terrain used for 3D map (E.g: 'Ellipsoid' or 'Cesium World Terrain')" - }, "title" : { "type" : "string" }, @@ -13615,54 +13498,6 @@ margin-bottom: 20px; "audioDeviceName" : { "type" : "string" }, - "gpioControl" : { - "type" : "integer", - "description" : "GPIO control\n * 0 - No GPIO control\n * 1 - Rx side controls GPIO\n * 2 - Tx side controls GPIO\n" - }, - "rx2txGPIOEnable" : { - "type" : "integer", - "description" : "Enable Rx to Tx GPIO control\n * 0 - disable\n * 1 - enable\n" - }, - "rx2txGPIOMask" : { - "type" : "integer", - "format" : "int8", - "description" : "Rx to Tx change GPIO mask" - }, - "rx2txGPIOValues" : { - "type" : "integer", - "format" : "int8", - "description" : "Rx to Tx change GPIO values" - }, - "rx2txCommandEnable" : { - "type" : "integer", - "description" : "Enable Rx to Tx command\n * 0 - disable\n * 1 - enable\n" - }, - "rx2txCommand" : { - "type" : "string", - "description" : "Command to be executed when Rx switches to Tx" - }, - "tx2rxGPIOEnable" : { - "type" : "integer", - "description" : "Enable Tx to Rx GPIO control\n * 0 - disable\n * 1 - enable\n" - }, - "tx2rxGPIOMask" : { - "type" : "integer", - "format" : "int8", - "description" : "Tx to Rx change GPIO mask" - }, - "tx2rxGPIOValues" : { - "type" : "integer", - "format" : "int8", - "description" : "Tx to Rx change GPIO values" - }, - "tx2rxCommandEnable" : { - "type" : "integer", - "description" : "Enable Tx to Rx command\n * 0 - disable\n * 1 - enable\n" - }, - "tx2rxCommand" : { - "type" : "string", - "description" : "Command to be executed when Tx switches to Rx" - }, "useReverseAPI" : { "type" : "integer", "description" : "Synchronize with reverse API (1 for yes, 0 for no)" @@ -57471,7 +57306,7 @@ except ApiException as e:
- Generated 2023-04-01T18:43:55.658+02:00 + Generated 2023-03-23T18:22:37.731+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/AaroniaRTSA.yaml b/sdrbase/resources/webapi/doc/swagger/include/AaroniaRTSA.yaml new file mode 100644 index 000000000..ff2348258 --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/AaroniaRTSA.yaml @@ -0,0 +1,29 @@ +AaroniaRTSASettings: + description: AaroniaRTSA + properties: + centerFrequency: + description: Sets the center frequency (Hz) of the distant IQ demodulator + type: integer + format: int64 + sampleRate: + description: Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator + type: integer + serverAddress: + description: Distant AaroniaRTSA instance URL or IPv4 address with port + type: string + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + +AaroniaRTSAReport: + description: AaroniaRTSA + properties: + status: + description: 0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected + type: integer diff --git a/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml b/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml index 62c8719f0..e69d36c93 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml @@ -71,3 +71,5 @@ DeviceReport: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxOutputReport" xtrxMIMOReport: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxMIMOReport" + aaroniaSDRReport: + $ref: "/doc/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAReport" diff --git a/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml index d3332a6ca..596f0e520 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml @@ -100,3 +100,5 @@ DeviceSettings: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxOutputSettings" xtrxMIMOSettings: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxMIMOSettings" + aaroniaRTSASettings: + $ref: "/doc/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSASettings" diff --git a/sdrgui/gui/valuedial.cpp b/sdrgui/gui/valuedial.cpp index 9222baa80..5bc7d5e91 100644 --- a/sdrgui/gui/valuedial.cpp +++ b/sdrgui/gui/valuedial.cpp @@ -108,6 +108,7 @@ void ValueDial::setColorMapper(ColorMapper colorMapper) void ValueDial::setValue(quint64 value) { m_valueNew = value; + m_textNew = formatText(m_valueNew); if (m_valueNew < m_valueMin) { m_valueNew = m_valueMin; @@ -115,16 +116,21 @@ void ValueDial::setValue(quint64 value) m_valueNew = m_valueMax; } - if (m_valueNew < m_value) { + if (m_valueNew < m_value) + { m_animationState = 1; - } else if (m_valueNew > m_value) { + } + else if (m_valueNew > m_value) + { m_animationState = -1; - } else { + } + else + { + m_text = m_textNew; return; } m_animationTimer.start(20); - m_textNew = formatText(m_valueNew); } void ValueDial::setValueRange(uint numDigits, quint64 min, quint64 max) diff --git a/swagger/docker/codegen/build.sh b/swagger/docker/codegen/build.sh index b1ac9a164..0e2267cda 100755 --- a/swagger/docker/codegen/build.sh +++ b/swagger/docker/codegen/build.sh @@ -18,7 +18,7 @@ EOF branch_name="sdrangel" clone_label=$(date) image_tag="latest" -uid=$(id -u) +uid=1000 docker_file="." while getopts "h?b:c:t:j:f:" opt; do diff --git a/swagger/docker/compose/compose.yml b/swagger/docker/compose/compose.yml index ec8ad4505..a4b2ba99f 100644 --- a/swagger/docker/compose/compose.yml +++ b/swagger/docker/compose/compose.yml @@ -2,6 +2,7 @@ version: '3' services: swgcodegen: image: "sdrangel/swagger/codegen:${IMAGE_CODEGEN_VERSION}" + user: "1000:1000" container_name: "sdrangel_swgcodegen" volumes: - "${SDRANGEL_BASE}:/opt/build/sdrangel:rw" @@ -12,6 +13,7 @@ services: tty: true swgserver: image: "sdrangel/swagger/server:${IMAGE_SERVER_VERSION}" + user: "1000:1000" container_name: "sdrangel_swgserver" volumes: - "${SDRANGEL_BASE}:/opt/build/sdrangel:rw" diff --git a/swagger/docker/compose/run.sh b/swagger/docker/compose/run.sh index 9e6429aa3..182f8e5c8 100755 --- a/swagger/docker/compose/run.sh +++ b/swagger/docker/compose/run.sh @@ -51,4 +51,4 @@ export IMAGE_CODEGEN_VERSION=${image_tag_codegen} export IMAGE_SERVER_VERSION=${image_tag_server} export SDRANGEL_BASE=${sdrangel_codebase} -docker-compose -f compose.yml ${stack_name} ${action} +docker compose -f compose.yml ${stack_name} ${action} diff --git a/swagger/docker/server/build.sh b/swagger/docker/server/build.sh index 7f4bf0ff8..cf532375b 100755 --- a/swagger/docker/server/build.sh +++ b/swagger/docker/server/build.sh @@ -15,7 +15,7 @@ EOF image_name="sdrangel/swagger/server" image_tag="latest" -uid=$(id -u) +uid=1000 docker_file="." while getopts "h?t:f:" opt; do diff --git a/swagger/sdrangel/api/swagger/include/AaroniaRTSA.yaml b/swagger/sdrangel/api/swagger/include/AaroniaRTSA.yaml new file mode 100644 index 000000000..ff2348258 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/AaroniaRTSA.yaml @@ -0,0 +1,29 @@ +AaroniaRTSASettings: + description: AaroniaRTSA + properties: + centerFrequency: + description: Sets the center frequency (Hz) of the distant IQ demodulator + type: integer + format: int64 + sampleRate: + description: Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator + type: integer + serverAddress: + description: Distant AaroniaRTSA instance URL or IPv4 address with port + type: string + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + +AaroniaRTSAReport: + description: AaroniaRTSA + properties: + status: + description: 0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected + type: integer diff --git a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml index 598a0e910..ed2423e11 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml @@ -71,3 +71,5 @@ DeviceReport: $ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxOutputReport" xtrxMIMOReport: $ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxMIMOReport" + aaroniaSDRReport: + $ref: "http://swgserver:8081/api/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAReport" diff --git a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml index 885376b44..71e7c8cc4 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml @@ -100,3 +100,5 @@ DeviceSettings: $ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxOutputSettings" xtrxMIMOSettings: $ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxMIMOSettings" + aaroniaRTSASettings: + $ref: "http://swgserver:8081/api/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSASettings" diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index a9de3b3cf..1ba852b64 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -2097,6 +2097,46 @@ margin-bottom: 20px; } }, "description" : "ATVMod" +}; + defs.AaroniaRTSAReport = { + "properties" : { + "status" : { + "type" : "integer", + "description" : "0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected" + } + }, + "description" : "AaroniaRTSA" +}; + defs.AaroniaRTSASettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64", + "description" : "Sets the center frequency (Hz) of the distant IQ demodulator" + }, + "sampleRate" : { + "type" : "integer", + "description" : "Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator" + }, + "serverAddress" : { + "type" : "string", + "description" : "Distant AaroniaRTSA instance URL or IPv4 address with port" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + } + }, + "description" : "AaroniaRTSA" }; defs.AirspyHFReport = { "properties" : { @@ -3538,9 +3578,6 @@ margin-bottom: 20px; "HeatMapReport" : { "$ref" : "#/definitions/HeatMapReport" }, - "ILSDemodReport" : { - "$ref" : "#/definitions/ILSDemodReport" - }, "M17DemodReport" : { "$ref" : "#/definitions/M17DemodReport" }, @@ -3705,9 +3742,6 @@ margin-bottom: 20px; "HeatMapSettings" : { "$ref" : "#/definitions/HeatMapSettings" }, - "ILSDemodSettings" : { - "$ref" : "#/definitions/ILSDemodSettings" - }, "InterferometerSettings" : { "$ref" : "#/definitions/InterferometerSettings" }, @@ -5205,6 +5239,9 @@ margin-bottom: 20px; }, "xtrxMIMOReport" : { "$ref" : "#/definitions/XtrxMIMOReport" + }, + "aaroniaSDRReport" : { + "$ref" : "#/definitions/AaroniaRTSAReport" } }, "description" : "Base device report. Only the device report corresponding to the device specified in the deviceHwType is or should be present." @@ -5393,6 +5430,9 @@ margin-bottom: 20px; }, "xtrxMIMOSettings" : { "$ref" : "#/definitions/XtrxMIMOSettings" + }, + "aaroniaRTSASettings" : { + "$ref" : "#/definitions/AaroniaRTSASettings" } }, "description" : "Base device settings. Only the device settings corresponding to the device specified in the deviceHwType field is or should be present." @@ -7413,143 +7453,6 @@ margin-bottom: 20px; } }, "description" : "IEEE_802_15_4_Mod" -}; - defs.ILSDemodReport = { - "properties" : { - "channelPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "power received in channel (dB)" - }, - "channelSampleRate" : { - "type" : "integer" - } - }, - "description" : "ILSDemod" -}; - defs.ILSDemodSettings = { - "properties" : { - "inputFrequencyOffset" : { - "type" : "integer", - "format" : "int64" - }, - "rfBandwidth" : { - "type" : "number", - "format" : "float" - }, - "mode" : { - "type" : "integer", - "description" : "(0 for LOC, 1 for G/S)" - }, - "frequencyIndex" : { - "type" : "integer" - }, - "squelch" : { - "type" : "integer" - }, - "volume" : { - "type" : "number", - "format" : "float" - }, - "audioMute" : { - "type" : "integer" - }, - "average" : { - "type" : "integer" - }, - "ddmUnits" : { - "type" : "integer" - }, - "identThreshold" : { - "type" : "number", - "format" : "float" - }, - "ident" : { - "type" : "string" - }, - "runway" : { - "type" : "string" - }, - "trueBearing" : { - "type" : "number", - "format" : "float" - }, - "latitude" : { - "type" : "string" - }, - "longitude" : { - "type" : "string" - }, - "elevation" : { - "type" : "integer" - }, - "glidePath" : { - "type" : "number", - "format" : "float" - }, - "refHeight" : { - "type" : "number", - "format" : "float" - }, - "courseWidth" : { - "type" : "number", - "format" : "float" - }, - "udpEnabled" : { - "type" : "integer", - "description" : "Whether to forward DDM to specified UDP port" - }, - "udpAddress" : { - "type" : "string", - "description" : "UDP address to forward DDM to" - }, - "udpPort" : { - "type" : "integer", - "description" : "UDP port to forward DDM to" - }, - "logFilename" : { - "type" : "string" - }, - "logEnabled" : { - "type" : "integer" - }, - "rgbColor" : { - "type" : "integer" - }, - "title" : { - "type" : "string" - }, - "streamIndex" : { - "type" : "integer", - "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." - }, - "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" - }, - "scopeConfig" : { - "$ref" : "#/definitions/GLScope" - }, - "channelMarker" : { - "$ref" : "#/definitions/ChannelMarker" - }, - "rollupState" : { - "$ref" : "#/definitions/RollupState" - } - }, - "description" : "ILSDemod" }; defs.InstanceChannelsResponse = { "required" : [ "channelcount" ], @@ -9209,7 +9112,7 @@ margin-bottom: 20px; }, "altitudeReference" : { "type" : "integer", - "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND." + "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND" }, "animations" : { "type" : "array", @@ -9258,14 +9161,6 @@ margin-bottom: 20px; "availableUntil" : { "type" : "string", "description" : "Date and time until after which this item should no longer appear on 3D map" - }, - "colorValid" : { - "type" : "integer", - "description" : "0 - Use default color, 1 - Use specified color" - }, - "color" : { - "type" : "integer", - "description" : "RGBA for polygon and polyline" } }, "description" : "An item to draw on the map. Set image to an empty string to remove item from the map." @@ -9368,7 +9263,7 @@ margin-bottom: 20px; }, "altitudeReference" : { "type" : "integer", - "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND." + "description" : "0 - NONE (Absolute), 1 - CLAMP_TO_GROUND, 2 - RELATIVE_TO_GROUND, 3 - CLIP_TO_GROUND" }, "animations" : { "type" : "array", @@ -9417,14 +9312,6 @@ margin-bottom: 20px; "availableUntil" : { "type" : "string", "description" : "Date and time until after which this item should no longer appear on 3D map" - }, - "colorValid" : { - "type" : "integer", - "description" : "0 - Use default color, 1 - Use specified color" - }, - "color" : { - "type" : "integer", - "description" : "RGBA for polygon and polyline" } }, "description" : "An item to draw on the map. Set image to an empty string to remove item from the map." @@ -9444,10 +9331,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "Display object names on the map (1 for yes, 0 for no)" }, - "terrain" : { - "type" : "string", - "description" : "Terrain used for 3D map (E.g: 'Ellipsoid' or 'Cesium World Terrain')" - }, "title" : { "type" : "string" }, @@ -13615,54 +13498,6 @@ margin-bottom: 20px; "audioDeviceName" : { "type" : "string" }, - "gpioControl" : { - "type" : "integer", - "description" : "GPIO control\n * 0 - No GPIO control\n * 1 - Rx side controls GPIO\n * 2 - Tx side controls GPIO\n" - }, - "rx2txGPIOEnable" : { - "type" : "integer", - "description" : "Enable Rx to Tx GPIO control\n * 0 - disable\n * 1 - enable\n" - }, - "rx2txGPIOMask" : { - "type" : "integer", - "format" : "int8", - "description" : "Rx to Tx change GPIO mask" - }, - "rx2txGPIOValues" : { - "type" : "integer", - "format" : "int8", - "description" : "Rx to Tx change GPIO values" - }, - "rx2txCommandEnable" : { - "type" : "integer", - "description" : "Enable Rx to Tx command\n * 0 - disable\n * 1 - enable\n" - }, - "rx2txCommand" : { - "type" : "string", - "description" : "Command to be executed when Rx switches to Tx" - }, - "tx2rxGPIOEnable" : { - "type" : "integer", - "description" : "Enable Tx to Rx GPIO control\n * 0 - disable\n * 1 - enable\n" - }, - "tx2rxGPIOMask" : { - "type" : "integer", - "format" : "int8", - "description" : "Tx to Rx change GPIO mask" - }, - "tx2rxGPIOValues" : { - "type" : "integer", - "format" : "int8", - "description" : "Tx to Rx change GPIO values" - }, - "tx2rxCommandEnable" : { - "type" : "integer", - "description" : "Enable Tx to Rx command\n * 0 - disable\n * 1 - enable\n" - }, - "tx2rxCommand" : { - "type" : "string", - "description" : "Command to be executed when Tx switches to Rx" - }, "useReverseAPI" : { "type" : "integer", "description" : "Synchronize with reverse API (1 for yes, 0 for no)" @@ -57471,7 +57306,7 @@ except ApiException as e:
- Generated 2023-04-01T18:43:55.658+02:00 + Generated 2023-03-23T18:22:37.731+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.cpp b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.cpp new file mode 100644 index 000000000..40542c680 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.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 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: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGAaroniaRTSAReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGAaroniaRTSAReport::SWGAaroniaRTSAReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGAaroniaRTSAReport::SWGAaroniaRTSAReport() { + status = 0; + m_status_isSet = false; +} + +SWGAaroniaRTSAReport::~SWGAaroniaRTSAReport() { + this->cleanup(); +} + +void +SWGAaroniaRTSAReport::init() { + status = 0; + m_status_isSet = false; +} + +void +SWGAaroniaRTSAReport::cleanup() { + +} + +SWGAaroniaRTSAReport* +SWGAaroniaRTSAReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGAaroniaRTSAReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&status, pJson["status"], "qint32", ""); + +} + +QString +SWGAaroniaRTSAReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGAaroniaRTSAReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_status_isSet){ + obj->insert("status", QJsonValue(status)); + } + + return obj; +} + +qint32 +SWGAaroniaRTSAReport::getStatus() { + return status; +} +void +SWGAaroniaRTSAReport::setStatus(qint32 status) { + this->status = status; + this->m_status_isSet = true; +} + + +bool +SWGAaroniaRTSAReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_status_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.h b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.h new file mode 100644 index 000000000..efb9fe4d1 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSAReport.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 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: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGAaroniaRTSAReport.h + * + * AaroniaRTSA + */ + +#ifndef SWGAaroniaRTSAReport_H_ +#define SWGAaroniaRTSAReport_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGAaroniaRTSAReport: public SWGObject { +public: + SWGAaroniaRTSAReport(); + SWGAaroniaRTSAReport(QString* json); + virtual ~SWGAaroniaRTSAReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGAaroniaRTSAReport* fromJson(QString &jsonString) override; + + qint32 getStatus(); + void setStatus(qint32 status); + + + virtual bool isSet() override; + +private: + qint32 status; + bool m_status_isSet; + +}; + +} + +#endif /* SWGAaroniaRTSAReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.cpp b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.cpp new file mode 100644 index 000000000..e276b7d51 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.cpp @@ -0,0 +1,250 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGAaroniaRTSASettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGAaroniaRTSASettings::SWGAaroniaRTSASettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGAaroniaRTSASettings::SWGAaroniaRTSASettings() { + center_frequency = 0L; + m_center_frequency_isSet = false; + sample_rate = 0; + m_sample_rate_isSet = false; + server_address = nullptr; + m_server_address_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; +} + +SWGAaroniaRTSASettings::~SWGAaroniaRTSASettings() { + this->cleanup(); +} + +void +SWGAaroniaRTSASettings::init() { + center_frequency = 0L; + m_center_frequency_isSet = false; + sample_rate = 0; + m_sample_rate_isSet = false; + server_address = new QString(""); + m_server_address_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; +} + +void +SWGAaroniaRTSASettings::cleanup() { + + + if(server_address != nullptr) { + delete server_address; + } + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + +} + +SWGAaroniaRTSASettings* +SWGAaroniaRTSASettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGAaroniaRTSASettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(¢er_frequency, pJson["centerFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&server_address, pJson["serverAddress"], "QString", "QString"); + + ::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", ""); + +} + +QString +SWGAaroniaRTSASettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGAaroniaRTSASettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_center_frequency_isSet){ + obj->insert("centerFrequency", QJsonValue(center_frequency)); + } + if(m_sample_rate_isSet){ + obj->insert("sampleRate", QJsonValue(sample_rate)); + } + if(server_address != nullptr && *server_address != QString("")){ + toJsonValue(QString("serverAddress"), server_address, obj, QString("QString")); + } + 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)); + } + + return obj; +} + +qint64 +SWGAaroniaRTSASettings::getCenterFrequency() { + return center_frequency; +} +void +SWGAaroniaRTSASettings::setCenterFrequency(qint64 center_frequency) { + this->center_frequency = center_frequency; + this->m_center_frequency_isSet = true; +} + +qint32 +SWGAaroniaRTSASettings::getSampleRate() { + return sample_rate; +} +void +SWGAaroniaRTSASettings::setSampleRate(qint32 sample_rate) { + this->sample_rate = sample_rate; + this->m_sample_rate_isSet = true; +} + +QString* +SWGAaroniaRTSASettings::getServerAddress() { + return server_address; +} +void +SWGAaroniaRTSASettings::setServerAddress(QString* server_address) { + this->server_address = server_address; + this->m_server_address_isSet = true; +} + +qint32 +SWGAaroniaRTSASettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGAaroniaRTSASettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGAaroniaRTSASettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGAaroniaRTSASettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGAaroniaRTSASettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGAaroniaRTSASettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGAaroniaRTSASettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGAaroniaRTSASettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + + +bool +SWGAaroniaRTSASettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_center_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_sample_rate_isSet){ + isObjectUpdated = true; break; + } + if(server_address && *server_address != QString("")){ + 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; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.h b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.h new file mode 100644 index 000000000..17544a716 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGAaroniaRTSASettings.h @@ -0,0 +1,95 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGAaroniaRTSASettings.h + * + * AaroniaRTSA + */ + +#ifndef SWGAaroniaRTSASettings_H_ +#define SWGAaroniaRTSASettings_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGAaroniaRTSASettings: public SWGObject { +public: + SWGAaroniaRTSASettings(); + SWGAaroniaRTSASettings(QString* json); + virtual ~SWGAaroniaRTSASettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGAaroniaRTSASettings* fromJson(QString &jsonString) override; + + qint64 getCenterFrequency(); + void setCenterFrequency(qint64 center_frequency); + + qint32 getSampleRate(); + void setSampleRate(qint32 sample_rate); + + QString* getServerAddress(); + void setServerAddress(QString* server_address); + + 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); + + + virtual bool isSet() override; + +private: + qint64 center_frequency; + bool m_center_frequency_isSet; + + qint32 sample_rate; + bool m_sample_rate_isSet; + + QString* server_address; + bool m_server_address_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; + +}; + +} + +#endif /* SWGAaroniaRTSASettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp index bf5d41523..0de2461ff 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp @@ -92,6 +92,8 @@ SWGDeviceReport::SWGDeviceReport() { m_xtrx_output_report_isSet = false; xtrx_mimo_report = nullptr; m_xtrx_mimo_report_isSet = false; + aaronia_sdr_report = nullptr; + m_aaronia_sdr_report_isSet = false; } SWGDeviceReport::~SWGDeviceReport() { @@ -164,6 +166,8 @@ SWGDeviceReport::init() { m_xtrx_output_report_isSet = false; xtrx_mimo_report = new SWGXtrxMIMOReport(); m_xtrx_mimo_report_isSet = false; + aaronia_sdr_report = new SWGAaroniaRTSAReport(); + m_aaronia_sdr_report_isSet = false; } void @@ -262,6 +266,9 @@ SWGDeviceReport::cleanup() { if(xtrx_mimo_report != nullptr) { delete xtrx_mimo_report; } + if(aaronia_sdr_report != nullptr) { + delete aaronia_sdr_report; + } } SWGDeviceReport* @@ -339,6 +346,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&xtrx_mimo_report, pJson["xtrxMIMOReport"], "SWGXtrxMIMOReport", "SWGXtrxMIMOReport"); + ::SWGSDRangel::setValue(&aaronia_sdr_report, pJson["aaroniaSDRReport"], "SWGAaroniaRTSAReport", "SWGAaroniaRTSAReport"); + } QString @@ -451,6 +460,9 @@ SWGDeviceReport::asJsonObject() { if((xtrx_mimo_report != nullptr) && (xtrx_mimo_report->isSet())){ toJsonValue(QString("xtrxMIMOReport"), xtrx_mimo_report, obj, QString("SWGXtrxMIMOReport")); } + if((aaronia_sdr_report != nullptr) && (aaronia_sdr_report->isSet())){ + toJsonValue(QString("aaroniaSDRReport"), aaronia_sdr_report, obj, QString("SWGAaroniaRTSAReport")); + } return obj; } @@ -775,6 +787,16 @@ SWGDeviceReport::setXtrxMimoReport(SWGXtrxMIMOReport* xtrx_mimo_report) { this->m_xtrx_mimo_report_isSet = true; } +SWGAaroniaRTSAReport* +SWGDeviceReport::getAaroniaSdrReport() { + return aaronia_sdr_report; +} +void +SWGDeviceReport::setAaroniaSdrReport(SWGAaroniaRTSAReport* aaronia_sdr_report) { + this->aaronia_sdr_report = aaronia_sdr_report; + this->m_aaronia_sdr_report_isSet = true; +} + bool SWGDeviceReport::isSet(){ @@ -876,6 +898,9 @@ SWGDeviceReport::isSet(){ if(xtrx_mimo_report && xtrx_mimo_report->isSet()){ isObjectUpdated = true; break; } + if(aaronia_sdr_report && aaronia_sdr_report->isSet()){ + isObjectUpdated = true; break; + } }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h index eed02397b..f15637463 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h @@ -22,6 +22,7 @@ #include +#include "SWGAaroniaRTSAReport.h" #include "SWGAirspyHFReport.h" #include "SWGAirspyReport.h" #include "SWGBladeRF2InputReport.h" @@ -167,6 +168,9 @@ public: SWGXtrxMIMOReport* getXtrxMimoReport(); void setXtrxMimoReport(SWGXtrxMIMOReport* xtrx_mimo_report); + SWGAaroniaRTSAReport* getAaroniaSdrReport(); + void setAaroniaSdrReport(SWGAaroniaRTSAReport* aaronia_sdr_report); + virtual bool isSet() override; @@ -267,6 +271,9 @@ private: SWGXtrxMIMOReport* xtrx_mimo_report; bool m_xtrx_mimo_report_isSet; + SWGAaroniaRTSAReport* aaronia_sdr_report; + bool m_aaronia_sdr_report_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp index b4dad838a..6932cefb4 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp @@ -120,6 +120,8 @@ SWGDeviceSettings::SWGDeviceSettings() { m_xtrx_output_settings_isSet = false; xtrx_mimo_settings = nullptr; m_xtrx_mimo_settings_isSet = false; + aaronia_rtsa_settings = nullptr; + m_aaronia_rtsa_settings_isSet = false; } SWGDeviceSettings::~SWGDeviceSettings() { @@ -220,6 +222,8 @@ SWGDeviceSettings::init() { m_xtrx_output_settings_isSet = false; xtrx_mimo_settings = new SWGXtrxMIMOSettings(); m_xtrx_mimo_settings_isSet = false; + aaronia_rtsa_settings = new SWGAaroniaRTSASettings(); + m_aaronia_rtsa_settings_isSet = false; } void @@ -358,6 +362,9 @@ SWGDeviceSettings::cleanup() { if(xtrx_mimo_settings != nullptr) { delete xtrx_mimo_settings; } + if(aaronia_rtsa_settings != nullptr) { + delete aaronia_rtsa_settings; + } } SWGDeviceSettings* @@ -463,6 +470,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&xtrx_mimo_settings, pJson["xtrxMIMOSettings"], "SWGXtrxMIMOSettings", "SWGXtrxMIMOSettings"); + ::SWGSDRangel::setValue(&aaronia_rtsa_settings, pJson["aaroniaRTSASettings"], "SWGAaroniaRTSASettings", "SWGAaroniaRTSASettings"); + } QString @@ -617,6 +626,9 @@ SWGDeviceSettings::asJsonObject() { if((xtrx_mimo_settings != nullptr) && (xtrx_mimo_settings->isSet())){ toJsonValue(QString("xtrxMIMOSettings"), xtrx_mimo_settings, obj, QString("SWGXtrxMIMOSettings")); } + if((aaronia_rtsa_settings != nullptr) && (aaronia_rtsa_settings->isSet())){ + toJsonValue(QString("aaroniaRTSASettings"), aaronia_rtsa_settings, obj, QString("SWGAaroniaRTSASettings")); + } return obj; } @@ -1081,6 +1093,16 @@ SWGDeviceSettings::setXtrxMimoSettings(SWGXtrxMIMOSettings* xtrx_mimo_settings) this->m_xtrx_mimo_settings_isSet = true; } +SWGAaroniaRTSASettings* +SWGDeviceSettings::getAaroniaRtsaSettings() { + return aaronia_rtsa_settings; +} +void +SWGDeviceSettings::setAaroniaRtsaSettings(SWGAaroniaRTSASettings* aaronia_rtsa_settings) { + this->aaronia_rtsa_settings = aaronia_rtsa_settings; + this->m_aaronia_rtsa_settings_isSet = true; +} + bool SWGDeviceSettings::isSet(){ @@ -1224,6 +1246,9 @@ SWGDeviceSettings::isSet(){ if(xtrx_mimo_settings && xtrx_mimo_settings->isSet()){ isObjectUpdated = true; break; } + if(aaronia_rtsa_settings && aaronia_rtsa_settings->isSet()){ + isObjectUpdated = true; break; + } }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h index 2fbabfd1a..43c988c91 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h @@ -22,6 +22,7 @@ #include +#include "SWGAaroniaRTSASettings.h" #include "SWGAirspyHFSettings.h" #include "SWGAirspySettings.h" #include "SWGAudioInputSettings.h" @@ -223,6 +224,9 @@ public: SWGXtrxMIMOSettings* getXtrxMimoSettings(); void setXtrxMimoSettings(SWGXtrxMIMOSettings* xtrx_mimo_settings); + SWGAaroniaRTSASettings* getAaroniaRtsaSettings(); + void setAaroniaRtsaSettings(SWGAaroniaRTSASettings* aaronia_rtsa_settings); + virtual bool isSet() override; @@ -365,6 +369,9 @@ private: SWGXtrxMIMOSettings* xtrx_mimo_settings; bool m_xtrx_mimo_settings_isSet; + SWGAaroniaRTSASettings* aaronia_rtsa_settings; + bool m_aaronia_rtsa_settings_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 560d7894b..c628a7f18 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -43,6 +43,8 @@ #include "SWGATVDemodSettings.h" #include "SWGATVModReport.h" #include "SWGATVModSettings.h" +#include "SWGAaroniaRTSAReport.h" +#include "SWGAaroniaRTSASettings.h" #include "SWGAirspyHFReport.h" #include "SWGAirspyHFSettings.h" #include "SWGAirspyReport.h" @@ -498,6 +500,16 @@ namespace SWGSDRangel { obj->init(); return obj; } + if(QString("SWGAaroniaRTSAReport").compare(type) == 0) { + SWGAaroniaRTSAReport *obj = new SWGAaroniaRTSAReport(); + obj->init(); + return obj; + } + if(QString("SWGAaroniaRTSASettings").compare(type) == 0) { + SWGAaroniaRTSASettings *obj = new SWGAaroniaRTSASettings(); + obj->init(); + return obj; + } if(QString("SWGAirspyHFReport").compare(type) == 0) { SWGAirspyHFReport *obj = new SWGAirspyHFReport(); obj->init();