From fc3f6d1711809e336fb833c84561133678d39705 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 26 Dec 2018 16:39:48 +0100 Subject: [PATCH] Reverse API: PlutoSDR input --- .../plutosdrinput/plutosdrinput.cpp | 195 ++++++++++++++++++ .../plutosdrinput/plutosdrinput.h | 13 +- .../plutosdrinput/plutosdrinputgui.cpp | 24 +++ .../plutosdrinput/plutosdrinputgui.h | 1 + .../plutosdrinput/plutosdrinputplugin.cpp | 2 +- .../plutosdrinput/plutosdrinputsettings.cpp | 20 ++ .../plutosdrinput/plutosdrinputsettings.h | 4 + 7 files changed, 257 insertions(+), 2 deletions(-) diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index c56c35a36..85e495d6f 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -15,6 +15,8 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include +#include #include "SWGDeviceSettings.h" #include "SWGDeviceState.h" @@ -59,10 +61,15 @@ PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) : m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); } PlutoSDRInput::~PlutoSDRInput() { + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; suspendBuddies(); @@ -226,6 +233,10 @@ bool PlutoSDRInput::handleMessage(const Message& message) m_deviceAPI->stopAcquisition(); } + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + return true; } else if (DevicePlutoSDRShared::MsgCrossReportToBuddy::match(message)) // message from buddy @@ -352,15 +363,19 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo bool suspendAllOtherThreads = false; // All others means Tx in fact DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); QLocale loc; + QList reverseAPIKeys; qDebug().noquote() << "PlutoSDRInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" << " m_devSampleRate: " << loc.toString(m_settings.m_devSampleRate) << "S/s" << " m_LOppmTenths: " << m_settings.m_LOppmTenths + << " m_dcBlock: " << m_settings.m_dcBlock + << " m_iqCorrection: " << m_settings.m_iqCorrection << " m_lpfFIREnable: " << m_settings.m_lpfFIREnable << " m_lpfFIRBW: " << loc.toString(m_settings.m_lpfFIRBW) << " m_lpfFIRlog2Decim: " << m_settings.m_lpfFIRlog2Decim << " m_lpfFIRGain: " << m_settings.m_lpfFIRGain << " m_log2Decim: " << loc.toString(1<set_params(DevicePlutoSDRBox::DEVICE_PHY, params); } + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + m_settings = settings; if (suspendAllOtherThreads) @@ -789,3 +868,119 @@ void PlutoSDRInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& respo fetchTemperature(); response.getPlutoSdrInputReport()->setTemperature(getTemperature()); } + +void PlutoSDRInput::webapiReverseSendSettings(QList& deviceSettingsKeys, const PlutoSDRInputSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setTx(0); + swgDeviceSettings->setDeviceHwType(new QString("PlutoSDR")); + swgDeviceSettings->setPlutoSdrInputSettings(new SWGSDRangel::SWGPlutoSdrInputSettings()); + SWGSDRangel::SWGPlutoSdrInputSettings *swgPlutoSdrInputSettings = swgDeviceSettings->getPlutoSdrInputSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgPlutoSdrInputSettings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("devSampleRate") || force) { + swgPlutoSdrInputSettings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("LOppmTenths") || force) { + swgPlutoSdrInputSettings->setLOppmTenths(settings.m_LOppmTenths); + } + if (deviceSettingsKeys.contains("lpfFIREnable") || force) { + swgPlutoSdrInputSettings->setLpfFirEnable(settings.m_lpfFIREnable ? 1 : 0); + } + if (deviceSettingsKeys.contains("lpfFIRBW") || force) { + swgPlutoSdrInputSettings->setLpfFirbw(settings.m_lpfFIRBW); + } + if (deviceSettingsKeys.contains("lpfFIRlog2Decim") || force) { + swgPlutoSdrInputSettings->setLpfFiRlog2Decim(settings.m_lpfFIRlog2Decim); + } + if (deviceSettingsKeys.contains("lpfFIRGain") || force) { + swgPlutoSdrInputSettings->setLpfFirGain(settings.m_lpfFIRGain); + } + if (deviceSettingsKeys.contains("fcPos") || force) { + swgPlutoSdrInputSettings->setFcPos((int) settings.m_fcPos); + } + if (deviceSettingsKeys.contains("dcBlock") || force) { + swgPlutoSdrInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("iqCorrection") || force) { + swgPlutoSdrInputSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("log2Decim") || force) { + swgPlutoSdrInputSettings->setLog2Decim(settings.m_log2Decim); + } + if (deviceSettingsKeys.contains("lpfBW") || force) { + swgPlutoSdrInputSettings->setLpfBw(settings.m_lpfBW); + } + if (deviceSettingsKeys.contains("gain") || force) { + swgPlutoSdrInputSettings->setGain(settings.m_gain); + } + if (deviceSettingsKeys.contains("antennaPath") || force) { + swgPlutoSdrInputSettings->setAntennaPath((int) settings.m_antennaPath); + } + if (deviceSettingsKeys.contains("gainMode") || force) { + swgPlutoSdrInputSettings->setGainMode((int) settings.m_gainMode); + } + if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) { + swgPlutoSdrInputSettings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency); + } + if (deviceSettingsKeys.contains("transverterMode") || force) { + swgPlutoSdrInputSettings->setTransverterMode(settings.m_transverterMode ? 1 : 0); + } + if (deviceSettingsKeys.contains("fileRecordName") || force) { + swgPlutoSdrInputSettings->setFileRecordName(new QString(settings.m_fileRecordName)); + } + + 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 + m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + + delete swgDeviceSettings; +} + +void PlutoSDRInput::webapiReverseSendStartStop(bool start) +{ + 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)); + + if (start) { + m_networkManager->sendCustomRequest(m_networkRequest, "POST"); + } else { + m_networkManager->sendCustomRequest(m_networkRequest, "DELETE"); + } +} + +void PlutoSDRInput::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "PlutoSDRInput::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + return; + } + + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("PlutoSDRInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); +} diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.h b/plugins/samplesource/plutosdrinput/plutosdrinput.h index a2191f755..5cc459425 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.h @@ -19,19 +19,23 @@ #include #include +#include #include "iio.h" -#include +#include "dsp/devicesamplesource.h" #include "util/message.h" #include "plutosdr/deviceplutosdrshared.h" #include "plutosdr/deviceplutosdrbox.h" #include "plutosdrinputsettings.h" +class QNetworkAccessManager; +class QNetworkReply; class DeviceSourceAPI; class FileRecord; class PlutoSDRInputThread; class PlutoSDRInput : public DeviceSampleSource { + Q_OBJECT public: class MsgConfigurePlutoSDR : public Message { MESSAGE_CLASS_DECLARATION @@ -154,6 +158,8 @@ public: PlutoSDRInputThread *m_plutoSDRInputThread; DevicePlutoSDRBox::SampleRates m_deviceSampleRates; QMutex m_mutex; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; bool openDevice(); void closeDevice(); @@ -162,6 +168,11 @@ public: bool applySettings(const PlutoSDRInputSettings& settings, bool force = false); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const PlutoSDRInputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const PlutoSDRInputSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +private slots: + void networkManagerFinished(QNetworkReply *reply); }; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp index 9121a91a0..01ad4867a 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp @@ -21,6 +21,8 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "gui/glspectrum.h" +#include "gui/crightclickenabler.h" +#include "gui/basicdevicesettingsdialog.h" #include "device/devicesourceapi.h" #include "device/deviceuiset.h" #include "plutosdr/deviceplutosdr.h" @@ -59,6 +61,9 @@ PlutoSDRInputGui::PlutoSDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : ui->swDecimLabel->setText(QString::fromUtf8("S\u2193")); ui->lpFIRDecimationLabel->setText(QString::fromUtf8("\u2193")); + CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); + connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); + blockApplySettings(true); displaySettings(); blockApplySettings(false); @@ -481,3 +486,22 @@ void PlutoSDRInputGui::updateSampleRateAndFrequency() m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); ui->deviceRateLabel->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5))); } + +void PlutoSDRInputGui::openDeviceSettingsDialog(const QPoint& p) +{ + 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); + 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(); + + sendSettings(); +} diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h index 0c5cba146..23a237b0e 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h @@ -97,6 +97,7 @@ private slots: void updateHardware(); void updateStatus(); void handleInputMessages(); + void openDeviceSettingsDialog(const QPoint& p); }; #endif /* PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ */ diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp index e840a6db1..bbfae06d6 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputplugin.cpp @@ -30,7 +30,7 @@ class DeviceSourceAPI; const PluginDescriptor PlutoSDRInputPlugin::m_pluginDescriptor = { QString("PlutoSDR Input"), - QString("4.3.1"), + QString("4.3.2"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp index 556977d75..3db0d2750 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp @@ -45,6 +45,10 @@ void PlutoSDRInputSettings::resetToDefaults() m_transverterMode = false; m_transverterDeltaFrequency = 0; m_fileRecordName = ""; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; } QByteArray PlutoSDRInputSettings::serialize() const @@ -67,6 +71,10 @@ QByteArray PlutoSDRInputSettings::serialize() const s.writeS32(15, (int) m_gainMode); s.writeBool(16, m_transverterMode); s.writeS64(17, m_transverterDeltaFrequency); + s.writeBool(18, m_useReverseAPI); + s.writeString(19, m_reverseAPIAddress); + s.writeU32(20, m_reverseAPIPort); + s.writeU32(21, m_reverseAPIDeviceIndex); return s.final(); } @@ -122,6 +130,18 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data) } d.readBool(16, &m_transverterMode, false); d.readS64(17, &m_transverterDeltaFrequency, 0); + d.readBool(18, &m_useReverseAPI, false); + d.readString(19, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(20, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(21, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; return true; } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h index 691161181..96861b263 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h @@ -75,6 +75,10 @@ struct PlutoSDRInputSettings { bool m_transverterMode; qint64 m_transverterDeltaFrequency; QString m_fileRecordName; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; PlutoSDRInputSettings(); void resetToDefaults();