mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-27 02:50:38 -04:00 
			
		
		
		
	Reverse API: SDR daemon sink
This commit is contained in:
		
							parent
							
								
									5a2e62aaea
								
							
						
					
					
						commit
						42d69204c6
					
				| @ -30,7 +30,7 @@ class DeviceSourceAPI; | ||||
| 
 | ||||
| const PluginDescriptor PlutoSDROutputPlugin::m_pluginDescriptor = { | ||||
| 	QString("PlutoSDR Output"), | ||||
| 	QString("4.3.1"), | ||||
| 	QString("4.3.2"), | ||||
| 	QString("(c) Edouard Griffiths, F4EXB"), | ||||
| 	QString("https://github.com/f4exb/sdrangel"), | ||||
| 	true, | ||||
|  | ||||
| @ -15,7 +15,6 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <QDebug> | ||||
| 
 | ||||
| #include <QTime> | ||||
| #include <QDateTime> | ||||
| #include <QString> | ||||
| @ -31,6 +30,8 @@ | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "gui/colormapper.h" | ||||
| #include "gui/glspectrum.h" | ||||
| #include "gui/crightclickenabler.h" | ||||
| #include "gui/basicdevicesettingsdialog.h" | ||||
| #include "dsp/dspengine.h" | ||||
| #include "dsp/dspcommands.h" | ||||
| 
 | ||||
| @ -95,6 +96,9 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) : | ||||
|     displayEventCounts(); | ||||
|     displayEventTimer(); | ||||
| 
 | ||||
|     CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); | ||||
|     connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); | ||||
| 
 | ||||
|     displaySettings(); | ||||
|     sendSettings(); | ||||
| } | ||||
| @ -624,3 +628,22 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject) | ||||
|         ui->infoText->setText(infoLine); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonSinkGui::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(); | ||||
| } | ||||
|  | ||||
| @ -154,6 +154,7 @@ private slots: | ||||
|     void updateStatus(); | ||||
| 	void tick(); | ||||
| 	void networkManagerFinished(QNetworkReply *reply); | ||||
|     void openDeviceSettingsDialog(const QPoint& p); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_FILESINKGUI_H
 | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
| #include <QNetworkAccessManager> | ||||
| #include <QNetworkReply> | ||||
| #include <QJsonParseError> | ||||
| #include <QBuffer> | ||||
| 
 | ||||
| #include "SWGDeviceSettings.h" | ||||
| #include "SWGDeviceState.h" | ||||
| @ -217,6 +218,10 @@ bool SDRdaemonSinkOutput::handleMessage(const Message& message) | ||||
|             m_deviceAPI->stopGeneration(); | ||||
|         } | ||||
| 
 | ||||
|         if (m_settings.m_useReverseAPI) { | ||||
|             webapiReverseSendStartStop(cmd.getStartStop()); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 	else if (MsgConfigureSDRdaemonSinkChunkCorrection::match(message)) | ||||
| @ -241,6 +246,20 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b | ||||
|     QMutexLocker mutexLocker(&m_mutex); | ||||
|     bool forwardChange = false; | ||||
|     bool changeTxDelay = false; | ||||
|     QList<QString> reverseAPIKeys; | ||||
| 
 | ||||
|     if ((m_settings.m_dataAddress != settings.m_dataAddress) || force) { | ||||
|         reverseAPIKeys.append("dataAddress"); | ||||
|     } | ||||
|     if ((m_settings.m_dataPort != settings.m_dataPort) || force) { | ||||
|         reverseAPIKeys.append("dataPort"); | ||||
|     } | ||||
|     if ((m_settings.m_apiAddress != settings.m_apiAddress) || force) { | ||||
|         reverseAPIKeys.append("apiAddress"); | ||||
|     } | ||||
|     if ((m_settings.m_apiPort != settings.m_apiPort) || force) { | ||||
|         reverseAPIKeys.append("apiPort"); | ||||
|     } | ||||
| 
 | ||||
|     if (force || (m_settings.m_dataAddress != settings.m_dataAddress) || (m_settings.m_dataPort != settings.m_dataPort)) | ||||
|     { | ||||
| @ -251,6 +270,8 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b | ||||
| 
 | ||||
|     if (force || (m_settings.m_sampleRate != settings.m_sampleRate)) | ||||
|     { | ||||
|         reverseAPIKeys.append("sampleRate"); | ||||
| 
 | ||||
|         if (m_sdrDaemonSinkThread != 0) { | ||||
|             m_sdrDaemonSinkThread->setSamplerate(settings.m_sampleRate); | ||||
|         } | ||||
| @ -264,6 +285,8 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b | ||||
| 
 | ||||
|     if (force || (m_settings.m_nbFECBlocks != settings.m_nbFECBlocks)) | ||||
|     { | ||||
|         reverseAPIKeys.append("nbFECBlocks"); | ||||
| 
 | ||||
|         if (m_sdrDaemonSinkThread != 0) { | ||||
|             m_sdrDaemonSinkThread->setNbBlocksFEC(settings.m_nbFECBlocks); | ||||
|         } | ||||
| @ -273,6 +296,7 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b | ||||
| 
 | ||||
|     if (force || (m_settings.m_txDelay != settings.m_txDelay)) | ||||
|     { | ||||
|         reverseAPIKeys.append("txDelay"); | ||||
|         changeTxDelay = true; | ||||
|     } | ||||
| 
 | ||||
| @ -300,6 +324,15 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b | ||||
|         m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| @ -461,7 +494,7 @@ void SDRdaemonSinkOutput::networkManagerFinished(QNetworkReply *reply) | ||||
| 
 | ||||
|         if (error.error == QJsonParseError::NoError) | ||||
|         { | ||||
|             analyzeApiReply(doc.object()); | ||||
|             analyzeApiReply(doc.object(), answer); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @ -476,7 +509,7 @@ void SDRdaemonSinkOutput::networkManagerFinished(QNetworkReply *reply) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject) | ||||
| void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject, const QString& answer) | ||||
| { | ||||
|     if (jsonObject.contains("DaemonSourceReport")) | ||||
|     { | ||||
| @ -546,6 +579,10 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject) | ||||
|         m_lastSampleCount = sampleCount; | ||||
|         m_lastQueueLength = queueLength; | ||||
|     } | ||||
|     else if (jsonObject.contains("sdrDaemonSinkSettings")) | ||||
|     { | ||||
|         qDebug("SDRdaemonSinkOutput::analyzeApiReply: reply:\n%s", answer.toStdString().c_str()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonSinkOutput::sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount) | ||||
| @ -559,3 +596,74 @@ void SDRdaemonSinkOutput::sampleRateCorrection(double remoteTimeDeltaUs, double | ||||
|     MsgConfigureSDRdaemonSinkChunkCorrection* message = MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection); | ||||
|     getInputMessageQueue()->push(message); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonSinkOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const SDRdaemonSinkSettings& settings, bool force) | ||||
| { | ||||
|     SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); | ||||
|     swgDeviceSettings->setTx(1); | ||||
|     swgDeviceSettings->setDeviceHwType(new QString("SDRdaemonSink")); | ||||
|     swgDeviceSettings->setSdrDaemonSinkSettings(new SWGSDRangel::SWGSDRdaemonSinkSettings()); | ||||
|     SWGSDRangel::SWGSDRdaemonSinkSettings *swgSdrDaemonSinkSettings = swgDeviceSettings->getSdrDaemonSinkSettings(); | ||||
| 
 | ||||
|     // transfer data that has been modified. When force is on transfer all data except reverse API data
 | ||||
| 
 | ||||
|     if (deviceSettingsKeys.contains("sampleRate") || force) { | ||||
|         swgSdrDaemonSinkSettings->setSampleRate(settings.m_sampleRate); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("txDelay") || force) { | ||||
|         swgSdrDaemonSinkSettings->setTxDelay(settings.m_txDelay); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("nbFECBlocks") || force) { | ||||
|         swgSdrDaemonSinkSettings->setNbFecBlocks(settings.m_nbFECBlocks); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("apiAddress") || force) { | ||||
|         swgSdrDaemonSinkSettings->setApiAddress(new QString(settings.m_apiAddress)); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("apiPort") || force) { | ||||
|         swgSdrDaemonSinkSettings->setApiPort(settings.m_apiPort); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("dataAddress") || force) { | ||||
|         swgSdrDaemonSinkSettings->setDataAddress(new QString(settings.m_dataAddress)); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("dataPort") || force) { | ||||
|         swgSdrDaemonSinkSettings->setDataPort(settings.m_dataPort); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("deviceIndex") || force) { | ||||
|         swgSdrDaemonSinkSettings->setDeviceIndex(settings.m_deviceIndex); | ||||
|     } | ||||
|     if (deviceSettingsKeys.contains("channelIndex") || force) { | ||||
|         swgSdrDaemonSinkSettings->setChannelIndex(settings.m_channelIndex); | ||||
|     } | ||||
| 
 | ||||
|     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 SDRdaemonSinkOutput::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"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -193,8 +193,10 @@ private: | ||||
|     void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SDRdaemonSinkSettings& settings); | ||||
|     void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); | ||||
| 
 | ||||
|     void analyzeApiReply(const QJsonObject& jsonObject); | ||||
|     void analyzeApiReply(const QJsonObject& jsonObject, const QString& answer); | ||||
|     void sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount); | ||||
|     void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const SDRdaemonSinkSettings& settings, bool force); | ||||
|     void webapiReverseSendStartStop(bool start); | ||||
| 
 | ||||
| private slots: | ||||
|     void tick(); | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| 
 | ||||
| const PluginDescriptor SDRdaemonSinkPlugin::m_pluginDescriptor = { | ||||
| 	QString("SDRdaemon sink output"), | ||||
| 	QString("4.1.0"), | ||||
| 	QString("4.3.2"), | ||||
| 	QString("(c) Edouard Griffiths, F4EXB"), | ||||
| 	QString("https://github.com/f4exb/sdrangel"), | ||||
| 	true, | ||||
|  | ||||
| @ -34,6 +34,10 @@ void SDRdaemonSinkSettings::resetToDefaults() | ||||
|     m_dataPort = 9090; | ||||
|     m_deviceIndex = 0; | ||||
|     m_channelIndex = 0; | ||||
|     m_useReverseAPI = false; | ||||
|     m_reverseAPIAddress = "127.0.0.1"; | ||||
|     m_reverseAPIPort = 8888; | ||||
|     m_reverseAPIDeviceIndex = 0; | ||||
| } | ||||
| 
 | ||||
| QByteArray SDRdaemonSinkSettings::serialize() const | ||||
| @ -50,6 +54,10 @@ QByteArray SDRdaemonSinkSettings::serialize() const | ||||
|     s.writeU32(8, m_dataPort); | ||||
|     s.writeU32(10, m_deviceIndex); | ||||
|     s.writeU32(11, m_channelIndex); | ||||
|     s.writeBool(12, m_useReverseAPI); | ||||
|     s.writeString(13, m_reverseAPIAddress); | ||||
|     s.writeU32(14, m_reverseAPIPort); | ||||
|     s.writeU32(15, m_reverseAPIDeviceIndex); | ||||
| 
 | ||||
|     return s.final(); | ||||
| } | ||||
| @ -80,6 +88,18 @@ bool SDRdaemonSinkSettings::deserialize(const QByteArray& data) | ||||
|         m_dataPort = uintval % (1<<16); | ||||
|         d.readU32(10, &m_deviceIndex, 0); | ||||
|         d.readU32(11, &m_channelIndex, 0); | ||||
|         d.readBool(12, &m_useReverseAPI, false); | ||||
|         d.readString(13, &m_reverseAPIAddress, "127.0.0.1"); | ||||
|         d.readU32(14, &uintval, 0); | ||||
| 
 | ||||
|         if ((uintval > 1023) && (uintval < 65535)) { | ||||
|             m_reverseAPIPort = uintval; | ||||
|         } else { | ||||
|             m_reverseAPIPort = 8888; | ||||
|         } | ||||
| 
 | ||||
|         d.readU32(15, &uintval, 0); | ||||
|         m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @ -30,6 +30,10 @@ struct SDRdaemonSinkSettings { | ||||
|     quint16 m_dataPort; | ||||
|     quint32 m_deviceIndex; | ||||
|     quint32 m_channelIndex; | ||||
|     bool     m_useReverseAPI; | ||||
|     QString  m_reverseAPIAddress; | ||||
|     uint16_t m_reverseAPIPort; | ||||
|     uint16_t m_reverseAPIDeviceIndex; | ||||
| 
 | ||||
|     SDRdaemonSinkSettings(); | ||||
|     void resetToDefaults(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user