kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			AFC: implemented full functionality
							rodzic
							
								
									1c1eade408
								
							
						
					
					
						commit
						977638d9d6
					
				|  | @ -25,14 +25,17 @@ | |||
| #include "SWGFeatureActions.h" | ||||
| #include "SWGAFCReport.h" | ||||
| #include "SWGDeviceState.h" | ||||
| #include "SWGChannelSettings.h" | ||||
| 
 | ||||
| #include "dsp/dspengine.h" | ||||
| #include "device/deviceset.h" | ||||
| #include "channel/channelapi.h" | ||||
| #include "maincore.h" | ||||
| 
 | ||||
| #include "afcworker.h" | ||||
| #include "afc.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(AFC::MsgConfigureAFC, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AFC::MsgPTT, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AFC::MsgStartStop, Message) | ||||
| 
 | ||||
| const QString AFC::m_featureIdURI = "sdrangel.feature.afc"; | ||||
|  | @ -40,7 +43,8 @@ const QString AFC::m_featureId = "AFC"; | |||
| 
 | ||||
| AFC::AFC(WebAPIAdapterInterface *webAPIAdapterInterface) : | ||||
|     Feature(m_featureIdURI, webAPIAdapterInterface), | ||||
|     m_ptt(false) | ||||
|     m_trackerDeviceSet(nullptr), | ||||
|     m_trackedDeviceSet(nullptr) | ||||
| { | ||||
|     setObjectName(m_featureId); | ||||
|     m_worker = new AFCWorker(webAPIAdapterInterface); | ||||
|  | @ -55,6 +59,7 @@ AFC::~AFC() | |||
|     } | ||||
| 
 | ||||
|     delete m_worker; | ||||
|     removeFeatureReferences(); | ||||
| } | ||||
| 
 | ||||
| void AFC::start() | ||||
|  | @ -90,17 +95,6 @@ bool AFC::handleMessage(const Message& cmd) | |||
| 
 | ||||
| 		return true; | ||||
| 	} | ||||
|     else if (MsgPTT::match(cmd)) | ||||
|     { | ||||
|         MsgPTT& cfg = (MsgPTT&) cmd; | ||||
|         m_ptt = cfg.getTx(); | ||||
|         qDebug() << "AFC::handleMessage: MsgPTT: tx:" << m_ptt; | ||||
| 
 | ||||
|         AFCWorker::MsgPTT *msg = AFCWorker::MsgPTT::create(m_ptt); | ||||
|         m_worker->getInputMessageQueue()->push(msg); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (MsgStartStop::match(cmd)) | ||||
|     { | ||||
|         MsgStartStop& cfg = (MsgStartStop&) cmd; | ||||
|  | @ -114,10 +108,25 @@ bool AFC::handleMessage(const Message& cmd) | |||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 	else | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|     else if (Feature::MsgChannelSettings::match(cmd)) | ||||
|     { | ||||
|         Feature::MsgChannelSettings& cfg = (Feature::MsgChannelSettings&) cmd; | ||||
|         SWGSDRangel::SWGChannelSettings *swgChannelSettings = cfg.getSWGSettings(); | ||||
|         QString *channelType  = swgChannelSettings->getChannelType(); | ||||
|         qDebug() << "AFC::handleMessage: Feature::MsgChannelSettings: " << *channelType; | ||||
| 
 | ||||
|         if (m_worker->isRunning()) | ||||
|         { | ||||
|             m_worker->getInputMessageQueue()->push(&cfg); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             delete swgChannelSettings; | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| QByteArray AFC::serialize() const | ||||
|  | @ -182,6 +191,14 @@ void AFC::applySettings(const AFCSettings& settings, bool force) | |||
|         reverseAPIKeys.append("freqTolerance"); | ||||
|     } | ||||
| 
 | ||||
|     if ((m_settings.m_trackerDeviceSetIndex != settings.m_trackerDeviceSetIndex) || force) { | ||||
|         trackerDeviceChange(settings.m_trackerDeviceSetIndex); | ||||
|     } | ||||
| 
 | ||||
|     if ((m_settings.m_trackedDeviceSetIndex != settings.m_trackedDeviceSetIndex) || force) { | ||||
|         trackedDeviceChange(settings.m_trackedDeviceSetIndex); | ||||
|     } | ||||
| 
 | ||||
|     AFCWorker::MsgConfigureAFCWorker *msg = AFCWorker::MsgConfigureAFCWorker::create( | ||||
|         settings, force | ||||
|     ); | ||||
|  | @ -266,20 +283,6 @@ int AFC::webapiActionsPost( | |||
| 
 | ||||
|     if (swgAFCActions) | ||||
|     { | ||||
|         if (featureActionsKeys.contains("ptt")) | ||||
|         { | ||||
|             bool ptt = swgAFCActions->getPtt() != 0; | ||||
| 
 | ||||
|             MsgPTT *msg = MsgPTT::create(ptt); | ||||
|             getInputMessageQueue()->push(msg); | ||||
| 
 | ||||
|             if (getMessageQueueToGUI()) | ||||
|             { | ||||
|                 MsgPTT *msgToGUI = MsgPTT::create(ptt); | ||||
|                 getMessageQueueToGUI()->push(msgToGUI); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return 202; | ||||
|     } | ||||
|     else | ||||
|  | @ -368,7 +371,6 @@ void AFC::webapiUpdateFeatureSettings( | |||
| 
 | ||||
| void AFC::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response) | ||||
| { | ||||
|     response.getAfcReport()->setPtt(m_ptt ? 1 : 0); | ||||
| } | ||||
| 
 | ||||
| void AFC::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const AFCSettings& settings, bool force) | ||||
|  | @ -447,3 +449,68 @@ void AFC::networkManagerFinished(QNetworkReply *reply) | |||
| 
 | ||||
|     reply->deleteLater(); | ||||
| } | ||||
| 
 | ||||
| void AFC::trackerDeviceChange(int deviceIndex) | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
|     m_trackerDeviceSet = mainCore->getDeviceSets()[deviceIndex]; | ||||
| 
 | ||||
|     for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) | ||||
|     { | ||||
|         ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); | ||||
| 
 | ||||
|         if (channel->getURI() == "sdrangel.channel.freqtracker") | ||||
|         { | ||||
|             channel->addFeatureSettingsFeedback(this); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFC::trackedDeviceChange(int deviceIndex) | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
|     m_trackedDeviceSet = mainCore->getDeviceSets()[deviceIndex]; | ||||
| 
 | ||||
|     for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) | ||||
|     { | ||||
|         ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); | ||||
| 
 | ||||
|         if (channel->getURI() != "sdrangel.channel.freqtracker") { | ||||
|             channel->addFeatureSettingsFeedback(this); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFC::removeFeatureReferences() | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
| 
 | ||||
|     if ((m_settings.m_trackerDeviceSetIndex >= 0) && (m_settings.m_trackerDeviceSetIndex < mainCore->getDeviceSets().size())) | ||||
|     { | ||||
|         DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackerDeviceSetIndex]; | ||||
| 
 | ||||
|         if (trackerDeviceSet == m_trackerDeviceSet) | ||||
|         { | ||||
|             for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) | ||||
|             { | ||||
|                 ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); | ||||
|                 channel->removeFeatureSettingsFeedback(this); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if ((m_settings.m_trackedDeviceSetIndex >= 0) && (m_settings.m_trackedDeviceSetIndex < mainCore->getDeviceSets().size())) | ||||
|     { | ||||
|         DeviceSet *trackerDeviceSet = mainCore->getDeviceSets()[m_settings.m_trackedDeviceSetIndex]; | ||||
| 
 | ||||
|         if (trackerDeviceSet == m_trackedDeviceSet) | ||||
|         { | ||||
|             for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) | ||||
|             { | ||||
|                 ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); | ||||
|                 channel->removeFeatureSettingsFeedback(this); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -26,10 +26,11 @@ | |||
| 
 | ||||
| #include "afcsettings.h" | ||||
| 
 | ||||
| class WebAPIAdapterInterface; | ||||
| class AFCWorker; | ||||
| class QNetworkAccessManager; | ||||
| class QNetworkReply; | ||||
| class WebAPIAdapterInterface; | ||||
| class DeviceSet; | ||||
| class AFCWorker; | ||||
| 
 | ||||
| namespace SWGSDRangel { | ||||
|     class SWGDeviceState; | ||||
|  | @ -61,25 +62,6 @@ public: | |||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     class MsgPTT : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         bool getTx() const { return m_tx; } | ||||
| 
 | ||||
|         static MsgPTT* create(bool tx) { | ||||
|             return new MsgPTT(tx); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         bool m_tx; | ||||
| 
 | ||||
|         MsgPTT(bool tx) : | ||||
|             Message(), | ||||
|             m_tx(tx) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     class MsgStartStop : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|  | @ -150,7 +132,8 @@ private: | |||
|     QThread m_thread; | ||||
|     AFCWorker *m_worker; | ||||
|     AFCSettings m_settings; | ||||
|     bool m_ptt; | ||||
|     DeviceSet *m_trackerDeviceSet; | ||||
|     DeviceSet *m_trackedDeviceSet; | ||||
| 
 | ||||
|     QNetworkAccessManager *m_networkManager; | ||||
|     QNetworkRequest m_networkRequest; | ||||
|  | @ -160,6 +143,9 @@ private: | |||
|     void applySettings(const AFCSettings& settings, bool force = false); | ||||
|     void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); | ||||
|     void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AFCSettings& settings, bool force); | ||||
|     void trackerDeviceChange(int deviceIndex); | ||||
|     void trackedDeviceChange(int deviceIndex); | ||||
|     void removeFeatureReferences(); | ||||
| 
 | ||||
| private slots: | ||||
|     void networkManagerFinished(QNetworkReply *reply); | ||||
|  |  | |||
|  | @ -127,7 +127,7 @@ | |||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="transverterTarget"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Use transverter or device frequency for tracker frequency adjustment</string> | ||||
|          <string>Use transverter frequency for tracker frequency adjustment</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>X</string> | ||||
|  |  | |||
|  | @ -19,21 +19,31 @@ | |||
| 
 | ||||
| #include "SWGDeviceState.h" | ||||
| #include "SWGSuccessResponse.h" | ||||
| #include "SWGDeviceSettings.h" | ||||
| #include "SWGChannelSettings.h" | ||||
| #include "SWGErrorResponse.h" | ||||
| 
 | ||||
| #include "webapi/webapiadapterinterface.h" | ||||
| #include "webapi/webapiutils.h" | ||||
| #include "device/deviceset.h" | ||||
| #include "device/deviceapi.h" | ||||
| #include "channel/channelapi.h" | ||||
| #include "feature/feature.h" | ||||
| #include "maincore.h" | ||||
| 
 | ||||
| #include "afcreport.h" | ||||
| #include "afcworker.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(AFCWorker::MsgConfigureAFCWorker, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AFCWorker::MsgPTT, Message) | ||||
| MESSAGE_CLASS_DEFINITION(AFCWorker::MsgTrackedDeviceChange, Message) | ||||
| 
 | ||||
| AFCWorker::AFCWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : | ||||
|     m_webAPIAdapterInterface(webAPIAdapterInterface), | ||||
|     m_msgQueueToGUI(nullptr), | ||||
|     m_running(false), | ||||
|     m_tx(false), | ||||
|     m_freqTracker(nullptr), | ||||
|     m_trackerDeviceFrequency(0), | ||||
|     m_trackerChannelOffset(0), | ||||
|     m_mutex(QMutex::Recursive) | ||||
| { | ||||
|     qDebug("AFCWorker::AFCWorker"); | ||||
|  | @ -81,14 +91,25 @@ bool AFCWorker::handleMessage(const Message& cmd) | |||
| { | ||||
|     if (MsgConfigureAFCWorker::match(cmd)) | ||||
|     { | ||||
|         qDebug() << "AFCWorker::handleMessage: MsgConfigureAFCWorker"; | ||||
|         QMutexLocker mutexLocker(&m_mutex); | ||||
|         MsgConfigureAFCWorker& cfg = (MsgConfigureAFCWorker&) cmd; | ||||
|         qDebug() << "AFCWorker::handleMessage: MsgConfigureAFCWorker"; | ||||
| 
 | ||||
|         applySettings(cfg.getSettings(), cfg.getForce()); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (Feature::MsgChannelSettings::match(cmd)) | ||||
|     { | ||||
|         qDebug() << "AFCWorker::handleMessage: Feature::MsgChannelSettings"; | ||||
|         QMutexLocker mutexLocker(&m_mutex); | ||||
|         Feature::MsgChannelSettings& cfg = (Feature::MsgChannelSettings&) cmd; | ||||
|         SWGSDRangel::SWGChannelSettings *swgChannelSettings = cfg.getSWGSettings(); | ||||
|         processChannelSettings(cfg.getChannelAPI(), cfg.getChannelSettingsKeys(), swgChannelSettings); | ||||
| 
 | ||||
|         delete swgChannelSettings; | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return false; | ||||
|  | @ -107,5 +128,341 @@ void AFCWorker::applySettings(const AFCSettings& settings, bool force) | |||
|             << " m_targetFrequency: " << settings.m_targetFrequency | ||||
|             << " m_freqTolerance: " << settings.m_freqTolerance | ||||
|             << " force: " << force; | ||||
| 
 | ||||
|     if ((settings.m_trackerDeviceSetIndex != m_settings.m_trackerDeviceSetIndex) || force) { | ||||
|         initTrackerDeviceSet(settings.m_trackerDeviceSetIndex); | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_trackedDeviceSetIndex != m_settings.m_trackedDeviceSetIndex) || force) { | ||||
|         initTrackedDeviceSet(settings.m_trackedDeviceSetIndex); | ||||
|     } | ||||
| 
 | ||||
|     m_settings = settings; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void AFCWorker::initTrackerDeviceSet(int deviceSetIndex) | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
|     m_trackerDeviceSet = mainCore->getDeviceSets()[deviceSetIndex]; | ||||
| 
 | ||||
|     for (int i = 0; i < m_trackerDeviceSet->getNumberOfChannels(); i++) | ||||
|     { | ||||
|         ChannelAPI *channel = m_trackerDeviceSet->getChannelAt(i); | ||||
| 
 | ||||
|         if (channel->getURI() == "sdrangel.channel.freqtracker") | ||||
|         { | ||||
|             m_freqTracker = channel; | ||||
|             SWGSDRangel::SWGDeviceSettings resDevice; | ||||
|             SWGSDRangel::SWGChannelSettings resChannel; | ||||
|             SWGSDRangel::SWGErrorResponse error; | ||||
| 
 | ||||
|             int rc = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(deviceSetIndex, resDevice, error); | ||||
| 
 | ||||
|             if (rc / 100 == 2) | ||||
|             { | ||||
|                 QJsonObject *jsonObj = resDevice.asJsonObject(); | ||||
|                 QJsonValue freqValue; | ||||
| 
 | ||||
|                 if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", freqValue)) | ||||
|                 { | ||||
|                     double freq = freqValue.toDouble(); | ||||
|                     m_trackerDeviceFrequency = freq; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device frequency"; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             rc = m_webAPIAdapterInterface->devicesetChannelSettingsGet(deviceSetIndex, i, resChannel, error); | ||||
| 
 | ||||
|             if (rc / 100 == 2) { | ||||
|                 m_trackerChannelOffset = resChannel.getFreqTrackerSettings()->getInputFrequencyOffset(); | ||||
|             } else { | ||||
|                 qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetChannelSettingsGet error" << rc << ":" << *error.getMessage(); | ||||
|             } | ||||
| 
 | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFCWorker::initTrackedDeviceSet(int deviceSetIndex) | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
|     m_trackedDeviceSet = mainCore->getDeviceSets()[deviceSetIndex]; | ||||
|     m_channelsMap.clear(); | ||||
| 
 | ||||
|     for (int i = 0; i < m_trackedDeviceSet->getNumberOfChannels(); i++) | ||||
|     { | ||||
|         ChannelAPI *channel = m_trackedDeviceSet->getChannelAt(i); | ||||
| 
 | ||||
|         if (channel->getURI() != "sdrangel.channel.freqtracker") | ||||
|         { | ||||
|             SWGSDRangel::SWGChannelSettings resChannel; | ||||
|             SWGSDRangel::SWGErrorResponse error; | ||||
| 
 | ||||
|             int rc = m_webAPIAdapterInterface->devicesetChannelSettingsGet(deviceSetIndex, i, resChannel, error); | ||||
| 
 | ||||
|             if (rc / 100 == 2) | ||||
|             { | ||||
|                 QJsonObject *jsonObj = resChannel.asJsonObject(); | ||||
|                 QJsonValue directionValue; | ||||
|                 QJsonValue channelOffsetValue; | ||||
| 
 | ||||
|                 if (WebAPIUtils::extractValue(*jsonObj, "direction", directionValue)) | ||||
|                 { | ||||
|                     int direction = directionValue.toInt(); | ||||
| 
 | ||||
|                     if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) | ||||
|                     { | ||||
|                         int channelOffset = channelOffsetValue.toInt(); | ||||
|                         m_channelsMap.insert(channel, ChannelTracking{channelOffset, m_trackerChannelOffset, direction}); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         qDebug() << "AFCWorker::initTrackedDeviceSet: cannot find channel offset frequency"; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     qDebug() << "AFCWorker::initTrackedDeviceSet: cannot find channel direction"; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 qDebug() << "AFCWorker::initTrackedDeviceSet: devicesetChannelSettingsGet error" << rc << ":" << *error.getMessage(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFCWorker::processChannelSettings( | ||||
|     const ChannelAPI *channelAPI, | ||||
|     const QList<QString> &channelSettingsKeys, | ||||
|     SWGSDRangel::SWGChannelSettings *swgChannelSettings) | ||||
| { | ||||
|     MainCore *mainCore = MainCore::instance(); | ||||
| 
 | ||||
|     if (*swgChannelSettings->getChannelType() == "FreqTracker") | ||||
|     { | ||||
|         m_trackerChannelOffset = swgChannelSettings->getFreqTrackerSettings()->getInputFrequencyOffset(); | ||||
|         QMap<ChannelAPI*, ChannelTracking>::iterator it = m_channelsMap.begin(); | ||||
| 
 | ||||
|         for (; it != m_channelsMap.end(); ++it) | ||||
|         { | ||||
|             if (mainCore->existsChannel(it.key())) | ||||
|             { | ||||
|                 int channelOffset = it.value().m_channelOffset + m_trackerChannelOffset - it.value().m_trackerOffset; | ||||
|                 updateChannelOffset(it.key(),it.value().m_channelDirection, channelOffset); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_channelsMap.erase(it); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (m_settings.m_hasTargetFrequency) { | ||||
|             updateTarget(); | ||||
|         } | ||||
|     } | ||||
|     else if (m_channelsMap.contains(const_cast<ChannelAPI*>(channelAPI))) | ||||
|     { | ||||
|         QJsonObject *jsonObj = swgChannelSettings->asJsonObject(); | ||||
|         QJsonValue channelOffsetValue; | ||||
| 
 | ||||
|         if (WebAPIUtils::extractValue(*jsonObj, "inputFrequencyOffset", channelOffsetValue)) | ||||
|         { | ||||
|             int channelOffset = channelOffsetValue.toInt(); | ||||
|             m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_channelOffset = channelOffset; | ||||
|             m_channelsMap[const_cast<ChannelAPI*>(channelAPI)].m_trackerOffset = m_trackerChannelOffset; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFCWorker::updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset) | ||||
| { | ||||
|     SWGSDRangel::SWGChannelSettings swgChannelSettings; | ||||
|     SWGSDRangel::SWGErrorResponse errorResponse; | ||||
|     QString channelId; | ||||
|     channelAPI->getIdentifier(channelId); | ||||
|     swgChannelSettings.init(); | ||||
|     qDebug() << "AFCWorker::updateChannelOffset:" << channelId << ":" << offset; | ||||
| 
 | ||||
|     QStringList channelSettingsKeys; | ||||
|     channelSettingsKeys.append("inputFrequencyOffset"); | ||||
|     QString jsonSettingsStr = tr("\"inputFrequencyOffset\":%1").arg(offset); | ||||
| 
 | ||||
|     QString jsonStr = tr("{ \"channelType\": \"%1\", \"direction\": \"%2\", \"%3Settings\": {%4}}") | ||||
|         .arg(QString(channelId)) | ||||
|         .arg(direction) | ||||
|         .arg(QString(channelId)) | ||||
|         .arg(jsonSettingsStr); | ||||
|     swgChannelSettings.fromJson(jsonStr); | ||||
| 
 | ||||
|     int httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch( | ||||
|         m_trackedDeviceSet->getIndex(), | ||||
|         channelAPI->getIndexInDeviceSet(), | ||||
|         false, // PATCH
 | ||||
|         channelSettingsKeys, | ||||
|         swgChannelSettings, | ||||
|         errorResponse | ||||
|     ); | ||||
| 
 | ||||
|     if (httpRC / 100 != 2) { | ||||
|         qDebug() << "AFCWorker::updateChannelOffset: error code" << httpRC << ":" << *errorResponse.getMessage(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void AFCWorker::updateTarget() | ||||
| { | ||||
|     SWGSDRangel::SWGDeviceSettings resDevice; | ||||
|     SWGSDRangel::SWGChannelSettings resChannel; | ||||
|     SWGSDRangel::SWGErrorResponse error; | ||||
| 
 | ||||
|     int rc = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(m_settings.m_trackerDeviceSetIndex, resDevice, error); | ||||
| 
 | ||||
|     if (rc / 100 == 2) | ||||
|     { | ||||
|         QJsonObject *jsonObj = resDevice.asJsonObject(); | ||||
|         QJsonValue freqValue; | ||||
| 
 | ||||
|         if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", freqValue)) | ||||
|         { | ||||
|             double freq = freqValue.toDouble(); | ||||
|             m_trackerDeviceFrequency = freq; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device frequency"; | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         qDebug() << "AFCWorker::initTrackerDeviceSet: devicesetDeviceSettingsGet error" << rc << ":" << *error.getMessage(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     int64_t trackerFrequency = m_trackerDeviceFrequency + m_trackerChannelOffset; | ||||
|     int64_t correction = m_settings.m_targetFrequency - trackerFrequency; | ||||
|     int64_t tolerance = m_settings.m_freqTolerance; | ||||
|     qDebug() << "AFCWorker::initTrackerDeviceSet: correction:" << correction << "tolerance:" << tolerance; | ||||
| 
 | ||||
|     if ((correction > -tolerance) && (correction < tolerance)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (m_settings.m_transverterTarget) // act on transverter
 | ||||
|     { | ||||
|         QJsonObject *jsonObj = resDevice.asJsonObject(); | ||||
|         QJsonValue xverterFrequencyValue; | ||||
| 
 | ||||
|         if (WebAPIUtils::extractValue(*jsonObj, "transverterDeltaFrequency", xverterFrequencyValue)) | ||||
|         { | ||||
|             double xverterFrequency = xverterFrequencyValue.toDouble(); | ||||
|             updateDeviceFrequency(m_trackerDeviceSet, "transverterDeltaFrequency", xverterFrequency + correction); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     else // act on device
 | ||||
|     { | ||||
|         QJsonObject *jsonObj = resDevice.asJsonObject(); | ||||
|         QJsonValue deviceFrequencyValue; | ||||
| 
 | ||||
|         if (WebAPIUtils::extractValue(*jsonObj, "centerFrequency", deviceFrequencyValue)) | ||||
|         { | ||||
|             double deviceFrequency = deviceFrequencyValue.toDouble(); | ||||
|             updateDeviceFrequency(m_trackerDeviceSet, "centerFrequency", deviceFrequency + correction); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             qDebug() << "AFCWorker::initTrackerDeviceSet: cannot find device transverter frequency"; | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool AFCWorker::updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency) | ||||
| { | ||||
|     SWGSDRangel::SWGDeviceSettings swgDeviceSettings; | ||||
|     SWGSDRangel::SWGErrorResponse errorResponse; | ||||
|     QStringList deviceSettingsKeys; | ||||
|     deviceSettingsKeys.append(key); | ||||
|     int deviceIndex = deviceSet->getIndex(); | ||||
|     DeviceAPI *deviceAPI = deviceSet->m_deviceAPI; | ||||
|     swgDeviceSettings.init(); | ||||
|     QString jsonSettingsStr = tr("\"%1\":%2").arg(key).arg(frequency); | ||||
|     QString deviceSettingsKey; | ||||
|     getDeviceSettingsKey(deviceAPI, deviceSettingsKey); | ||||
| 
 | ||||
|     QString jsonStr = tr("{ \"deviceHwType\": \"%1\", \"direction\": \"%2\", \"%3\": {%4}}") | ||||
|         .arg(deviceAPI->getHardwareId()) | ||||
|         .arg(getDeviceDirection(deviceAPI)) | ||||
|         .arg(deviceSettingsKey) | ||||
|         .arg(jsonSettingsStr); | ||||
|     swgDeviceSettings.fromJson(jsonStr); | ||||
|     qDebug() << "AFCWorker::updateDeviceFrequency:" << jsonStr; | ||||
| 
 | ||||
|     int httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch | ||||
|     ( | ||||
|         deviceIndex, | ||||
|         false, // PATCH
 | ||||
|         deviceSettingsKeys, | ||||
|         swgDeviceSettings, | ||||
|         errorResponse | ||||
|     ); | ||||
| 
 | ||||
|     if (httpRC / 100 != 2) | ||||
|     { | ||||
|         qDebug("AFCWorker::updateDeviceFrequency: error %d: %s", httpRC, qPrintable(*errorResponse.getMessage())); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| int AFCWorker::getDeviceDirection(DeviceAPI *deviceAPI) | ||||
| { | ||||
|     if (deviceAPI->getSampleSink()) { | ||||
|         return 1; | ||||
|     } else if (deviceAPI->getSampleMIMO()) { | ||||
|         return 2; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void AFCWorker::getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey) | ||||
| { | ||||
|     const QString& deviceHwId = deviceAPI->getHardwareId(); | ||||
| 
 | ||||
|     if (deviceAPI->getSampleSink()) | ||||
|     { | ||||
|         if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(deviceHwId)) { | ||||
|             settingsKey = WebAPIUtils::m_sinkDeviceHwIdToSettingsKey[deviceHwId]; | ||||
|         } | ||||
|     } | ||||
|     else if (deviceAPI->getSampleMIMO()) | ||||
|     { | ||||
|         if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(deviceHwId)) { | ||||
|             settingsKey = WebAPIUtils::m_mimoDeviceHwIdToSettingsKey[deviceHwId]; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(deviceHwId)) { | ||||
|             settingsKey = WebAPIUtils::m_sourceDeviceHwIdToSettingsKey[deviceHwId]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
| #define INCLUDE_FEATURE_AFCWORKER_H_ | ||||
| 
 | ||||
| #include <QObject> | ||||
| #include <QMap> | ||||
| #include <QTimer> | ||||
| 
 | ||||
| #include "util/message.h" | ||||
|  | @ -27,6 +28,8 @@ | |||
| #include "afcsettings.h" | ||||
| 
 | ||||
| class WebAPIAdapterInterface; | ||||
| class DeviceSet; | ||||
| class ChannelAPI; | ||||
| 
 | ||||
| class AFCWorker : public QObject | ||||
| { | ||||
|  | @ -55,22 +58,23 @@ public: | |||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     class MsgPTT : public Message { | ||||
|     class MsgTrackedDeviceChange : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         bool getTx() const { return m_tx; } | ||||
|         int getDeviceIndex() const { return m_deviceIndex; } | ||||
| 
 | ||||
|         static MsgPTT* create(bool tx) { | ||||
|             return new MsgPTT(tx); | ||||
|         static MsgTrackedDeviceChange* create(int deviceIndex) | ||||
|         { | ||||
|             return new MsgTrackedDeviceChange(deviceIndex); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         bool m_tx; | ||||
|         int m_deviceIndex; | ||||
| 
 | ||||
|         MsgPTT(bool tx) : | ||||
|         MsgTrackedDeviceChange(int deviceIndex) : | ||||
|             Message(), | ||||
|             m_tx(tx) | ||||
|             m_deviceIndex(deviceIndex) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|  | @ -84,17 +88,59 @@ public: | |||
|     void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; } | ||||
| 
 | ||||
| private: | ||||
|     struct ChannelTracking | ||||
|     { | ||||
|         int m_channelOffset; | ||||
|         int m_trackerOffset; | ||||
|         int m_channelDirection; | ||||
| 
 | ||||
|         ChannelTracking() : | ||||
|             m_channelOffset(0), | ||||
|             m_trackerOffset(0), | ||||
|             m_channelDirection(0) | ||||
|         {} | ||||
| 
 | ||||
|         ChannelTracking(int channelOffset, int trackerOffset, int channelDirection) : | ||||
|             m_channelOffset(channelOffset), | ||||
|             m_trackerOffset(trackerOffset), | ||||
|             m_channelDirection(m_channelDirection) | ||||
|         {} | ||||
| 
 | ||||
|         ChannelTracking(const ChannelTracking& other) : | ||||
|             m_channelOffset(other.m_channelOffset), | ||||
|             m_trackerOffset(other.m_trackerOffset), | ||||
|             m_channelDirection(other.m_channelDirection) | ||||
|         {} | ||||
|     }; | ||||
| 
 | ||||
|     WebAPIAdapterInterface *m_webAPIAdapterInterface; | ||||
| 	MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
 | ||||
|     MessageQueue *m_msgQueueToGUI; //!< Queue to report state to GUI
 | ||||
|     AFCSettings m_settings; | ||||
|     bool m_running; | ||||
|     bool m_tx; | ||||
|     DeviceSet *m_trackerDeviceSet; | ||||
|     DeviceSet *m_trackedDeviceSet; | ||||
|     ChannelAPI *m_freqTracker; | ||||
|     uint64_t m_trackerDeviceFrequency; | ||||
|     int m_trackerChannelOffset; | ||||
|     QMap<ChannelAPI*, ChannelTracking> m_channelsMap; | ||||
| 	QTimer m_updateTimer; | ||||
|     QMutex m_mutex; | ||||
| 
 | ||||
|     bool handleMessage(const Message& cmd); | ||||
|     void applySettings(const AFCSettings& settings, bool force = false); | ||||
|     void initTrackerDeviceSet(int deviceSetIndex); | ||||
|     void initTrackedDeviceSet(int deviceSetIndex); | ||||
|     void processChannelSettings( | ||||
|         const ChannelAPI *channelAPI, | ||||
|         const QList<QString> &channelSettingsKeys, | ||||
|         SWGSDRangel::SWGChannelSettings *swgChannelSettings | ||||
|     ); | ||||
|     void updateChannelOffset(ChannelAPI *channelAPI, int direction, int offset); | ||||
|     void updateTarget(); | ||||
|     bool updateDeviceFrequency(DeviceSet *deviceSet, const QString& key, int64_t frequency); | ||||
|     int getDeviceDirection(DeviceAPI *deviceAPI); | ||||
|     void getDeviceSettingsKey(DeviceAPI *deviceAPI, QString& settingsKey); | ||||
| 
 | ||||
| private slots: | ||||
|     void handleInputMessages(); | ||||
|  |  | |||
|  | @ -27,4 +27,15 @@ ChannelAPI::ChannelAPI(const QString& name, StreamType streamType) : | |||
|     m_deviceSetIndex(0), | ||||
|     m_deviceAPI(0), | ||||
|     m_uid(UidCalculator::getNewObjectId()) | ||||
| { } | ||||
| { } | ||||
| 
 | ||||
| void ChannelAPI::addFeatureSettingsFeedback(Feature *feature) | ||||
| { | ||||
|     m_featuresSettingsFeedback.removeOne(feature); | ||||
|     m_featuresSettingsFeedback.append(feature); | ||||
| } | ||||
| 
 | ||||
| void ChannelAPI::removeFeatureSettingsFeedback(Feature *feature) | ||||
| { | ||||
|     m_featuresSettingsFeedback.removeOne(feature); | ||||
| } | ||||
|  |  | |||
|  | @ -22,11 +22,14 @@ | |||
| 
 | ||||
| #include <QString> | ||||
| #include <QByteArray> | ||||
| #include <QList> | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #include "export.h" | ||||
| 
 | ||||
| class DeviceAPI; | ||||
| class Feature; | ||||
| 
 | ||||
| namespace SWGSDRangel | ||||
| { | ||||
|  | @ -116,12 +119,18 @@ public: | |||
|     void setDeviceAPI(DeviceAPI *deviceAPI) { m_deviceAPI = deviceAPI; } | ||||
|     uint64_t getUID() const { return m_uid; } | ||||
| 
 | ||||
|     // Features support
 | ||||
|     void addFeatureSettingsFeedback(Feature *feature); | ||||
|     void removeFeatureSettingsFeedback(Feature *feature); | ||||
| 
 | ||||
|     // MIMO support
 | ||||
|     StreamType getStreamType() const { return m_streamType; } | ||||
|     virtual int getNbSinkStreams() const = 0; | ||||
|     virtual int getNbSourceStreams() const = 0; | ||||
|     virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const = 0; | ||||
| 
 | ||||
| protected: | ||||
|     QList<Feature*> m_featuresSettingsFeedback; //!< list of features to report back settings changes in swagger API format
 | ||||
| 
 | ||||
| private: | ||||
|     StreamType m_streamType; | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ | |||
| 
 | ||||
| #include "feature.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(Feature::MsgChannelSettings, Message) | ||||
| 
 | ||||
| Feature::Feature(const QString& name, WebAPIAdapterInterface *webAPIAdapterInterface) : | ||||
|     m_name(name), | ||||
|     m_uid(UidCalculator::getNewObjectId()), | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ | |||
| #include "util/messagequeue.h" | ||||
| 
 | ||||
| class WebAPIAdapterInterface; | ||||
| class ChannelAPI; | ||||
| 
 | ||||
| namespace SWGSDRangel | ||||
| { | ||||
|  | @ -36,11 +37,50 @@ namespace SWGSDRangel | |||
|     class SWGFeatureReport; | ||||
|     class SWGFeatureActions; | ||||
|     class SWGDeviceState; | ||||
|     class SWGChannelSettings; | ||||
| } | ||||
| 
 | ||||
| class SDRBASE_API Feature : public QObject { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     class MsgChannelSettings : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         const ChannelAPI *getChannelAPI() const { return m_channelAPI; } | ||||
|         const QList<QString>& getChannelSettingsKeys() const { return m_channelSettingsKeys; } | ||||
|         SWGSDRangel::SWGChannelSettings *getSWGSettings() const { return m_swgSettings; } | ||||
|         bool getForce() const { return m_force; } | ||||
| 
 | ||||
|         static MsgChannelSettings* create( | ||||
|             const ChannelAPI *channelAPI, | ||||
|             const QList<QString>& channelSettingsKey, | ||||
|             SWGSDRangel::SWGChannelSettings *swgSettings, | ||||
|             bool force) | ||||
|         { | ||||
|             return new MsgChannelSettings(channelAPI, channelSettingsKey, swgSettings, force); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         const ChannelAPI *m_channelAPI; | ||||
|         QList<QString> m_channelSettingsKeys; | ||||
|         SWGSDRangel::SWGChannelSettings *m_swgSettings; | ||||
|         bool m_force; | ||||
| 
 | ||||
|         MsgChannelSettings( | ||||
|             const ChannelAPI *channelAPI, | ||||
|             const QList<QString>& channelSettingsKeys, | ||||
|             SWGSDRangel::SWGChannelSettings *swgSettings, | ||||
|             bool force | ||||
|         ) : | ||||
|             Message(), | ||||
|             m_channelAPI(channelAPI), | ||||
|             m_channelSettingsKeys(channelSettingsKeys), | ||||
|             m_swgSettings(swgSettings), | ||||
|             m_force(force) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     enum FeatureState { | ||||
| 		StNotStarted,  //!< feature is before initialization
 | ||||
| 		StIdle,        //!< feature is idle
 | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| 
 | ||||
| #include "httpdocrootsettings.h" | ||||
| #include "webapirequestmapper.h" | ||||
| #include "webapiutils.h" | ||||
| #include "SWGInstanceSummaryResponse.h" | ||||
| #include "SWGInstanceConfigResponse.h" | ||||
| #include "SWGInstanceDevicesResponse.h" | ||||
|  | @ -56,205 +57,6 @@ | |||
| #include "SWGFeatureReport.h" | ||||
| #include "SWGFeatureActions.h" | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_channelURIToSettingsKey = { | ||||
|     {"sdrangel.channel.amdemod", "AMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.am", "AMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modam", "AMModSettings"}, | ||||
|     {"sdrangel.channeltx.modatv", "ATVModSettings"}, | ||||
|     {"sdrangel.channel.bfm", "BFMDemodSettings"}, | ||||
|     {"sdrangel.channel.chanalyzer", "ChannelAnalyzerSettings"}, | ||||
|     {"sdrangel.channel.chanalyzerng", "ChannelAnalyzerSettings"}, // remap
 | ||||
|     {"org.f4exb.sdrangelove.channel.chanalyzer", "ChannelAnalyzerSettings"}, // remap
 | ||||
|     {"sdrangel.channel.demodatv", "ATVDemodSettings"}, | ||||
|     {"sdrangel.channel.demoddatv", "DATVDemodSettings"}, | ||||
|     {"sdrangel.channel.dsddemod", "DSDDemodSettings"}, | ||||
|     {"sdrangel.channel.filesink", "FileSinkSettings"}, | ||||
|     {"sdrangel.channeltx.filesource", "FileSourceSettings"}, | ||||
|     {"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"}, | ||||
|     {"sdrangel.channeltx.freedvmod", "FreeDVModSettings"}, | ||||
|     {"sdrangel.channel.freqtracker", "FreqTrackerSettings"}, | ||||
|     {"sdrangel.channel.nfmdemod", "NFMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modnfm", "NFMModSettings"}, | ||||
|     {"sdrangel.demod.localsink", "LocalSinkSettings"}, | ||||
|     {"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap
 | ||||
|     {"sdrangel.channel.localsource", "LocalSourceSettings"}, | ||||
|     {"sdrangel.channeltx.modpacket", "PacketModSettings"}, | ||||
|     {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, | ||||
|     {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, | ||||
|     {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, | ||||
|     {"sdrangel.channeltx.modssb", "SSBModSettings"}, | ||||
|     {"sdrangel.channel.ssbdemod", "SSBDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.ssb", "SSBDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.udpsource", "UDPSourceSettings"}, | ||||
|     {"sdrangel.channeltx.udpsink", "UDPSourceSettings"}, // remap
 | ||||
|     {"sdrangel.channel.udpsink", "UDPSinkSettings"}, | ||||
|     {"sdrangel.channel.udpsrc", "UDPSinkSettings"}, // remap
 | ||||
|     {"sdrangel.channel.wfmdemod", "WFMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.wfm", "WFMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modwfm", "WFMModSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_deviceIdToSettingsKey = { | ||||
|     {"sdrangel.samplesource.airspy", "airspySettings"}, | ||||
|     {"sdrangel.samplesource.airspyhf", "airspyHFSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf1input", "bladeRF1InputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf", "bladeRF1InputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesink.bladerf1output", "bladeRF1OutputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf1output", "bladeRF1OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.bladerfoutput", "bladeRF1OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.bladerf2input", "bladeRF2InputSettings"}, | ||||
|     {"sdrangel.samplesink.bladerf2output", "bladeRF2OutputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf2output", "bladeRF2OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.fcdpro", "fcdProSettings"}, | ||||
|     {"sdrangel.samplesource.fcdproplus", "fcdProPlusSettings"}, | ||||
|     {"sdrangel.samplesource.fileinput", "fileInputSettings"}, | ||||
|     {"sdrangel.samplesource.filesource", "fileInputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.hackrf", "hackRFInputSettings"}, | ||||
|     {"sdrangel.samplesink.hackrf", "hackRFOutputSettings"}, | ||||
|     {"sdrangel.samplesource.hackrfoutput", "hackRFOutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.kiwisdrsource", "kiwiSDRSettings"}, | ||||
|     {"sdrangel.samplesource.limesdr", "limeSdrInputSettings"}, | ||||
|     {"sdrangel.samplesink.limesdr", "limeSdrOutputSettings"}, | ||||
|     {"sdrangel.samplesource.localinput", "localInputSettings"}, | ||||
|     {"sdrangel.samplesink.localoutput", "localOutputSettings"}, | ||||
|     {"sdrangel.samplesource.localoutput", "localOutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.perseus", "perseusSettings"}, | ||||
|     {"sdrangel.samplesource.plutosdr", "plutoSdrInputSettings"}, | ||||
|     {"sdrangel.samplesink.plutosdr", "plutoSdrOutputSettings"}, | ||||
|     {"sdrangel.samplesource.rtlsdr", "rtlSdrSettings"}, | ||||
|     {"sdrangel.samplesource.remoteinput", "remoteInputSettings"}, | ||||
|     {"sdrangel.samplesink.remoteoutput", "remoteOutputSettings"}, | ||||
|     {"sdrangel.samplesource.sdrplay", "sdrPlaySettings"}, | ||||
|     {"sdrangel.samplesource.soapysdrinput", "soapySDRInputSettings"}, | ||||
|     {"sdrangel.samplesink.soapysdroutput", "soapySDROutputSettings"}, | ||||
|     {"sdrangel.samplesource.testsource", "testSourceSettings"}, | ||||
|     {"sdrangel.samplesource.usrp", "usrpInputSettings"}, | ||||
|     {"sdrangel.samplesink.usrp", "usrpOutputSettings"}, | ||||
|     {"sdrangel.samplesource.xtrx", "XtrxInputSettings"}, | ||||
|     {"sdrangel.samplesink.xtrx", "XtrxOutputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToSettingsKey = { | ||||
|     {"AMDemod", "AMDemodSettings"}, | ||||
|     {"AMMod", "AMModSettings"}, | ||||
|     {"ATVDemod", "ATVDemodSettings"}, | ||||
|     {"ATVMod", "ATVModSettings"}, | ||||
|     {"BFMDemod", "BFMDemodSettings"}, | ||||
|     {"ChannelAnalyzer", "ChannelAnalyzerSettings"}, | ||||
|     {"DATVDemod", "DATVDemodSettings"}, | ||||
|     {"DSDDemod", "DSDDemodSettings"}, | ||||
|     {"FileSink", "FileSinkSettings"}, | ||||
|     {"FileSource", "FileSourceSettings"}, | ||||
|     {"FreeDVDemod", "FreeDVDemodSettings"}, | ||||
|     {"FreeDVMod", "FreeDVModSettings"}, | ||||
|     {"FreqTracker", "FreqTrackerSettings"}, | ||||
|     {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"}, | ||||
|     {"NFMDemod", "NFMDemodSettings"}, | ||||
|     {"NFMMod", "NFMModSettings"}, | ||||
|     {"PacketMod", "PacketModSettings"}, | ||||
|     {"LocalSink", "LocalSinkSettings"}, | ||||
|     {"LocalSource", "LocalSourceSettings"}, | ||||
|     {"RemoteSink", "RemoteSinkSettings"}, | ||||
|     {"RemoteSource", "RemoteSourceSettings"}, | ||||
|     {"SSBMod", "SSBModSettings"}, | ||||
|     {"SSBDemod", "SSBDemodSettings"}, | ||||
|     {"UDPSink", "UDPSourceSettings"}, | ||||
|     {"UDPSource", "UDPSinkSettings"}, | ||||
|     {"WFMDemod", "WFMDemodSettings"}, | ||||
|     {"WFMMod", "WFMModSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToActionsKey = { | ||||
|     {"FileSink", "FileSinkActions"}, | ||||
|     {"FileSource", "FileSourceActions"}, | ||||
|     {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModActions"}, | ||||
|     {"PacketMod", "PacketModActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_sourceDeviceHwIdToSettingsKey = { | ||||
|     {"Airspy", "airspySettings"}, | ||||
|     {"AirspyHF", "airspyHFSettings"}, | ||||
|     {"BladeRF1", "bladeRF1InputSettings"}, | ||||
|     {"BladeRF2", "bladeRF2InputSettings"}, | ||||
|     {"FCDPro", "fcdProSettings"}, | ||||
|     {"FCDPro+", "fcdProPlusSettings"}, | ||||
|     {"FileInput", "fileInputSettings"}, | ||||
|     {"HackRF", "hackRFInputSettings"}, | ||||
|     {"KiwiSDR", "kiwiSDRSettings"}, | ||||
|     {"LimeSDR", "limeSdrInputSettings"}, | ||||
|     {"LocalInput", "localInputSettings"}, | ||||
|     {"Perseus", "perseusSettings"}, | ||||
|     {"PlutoSDR", "plutoSdrInputSettings"}, | ||||
|     {"RTLSDR", "rtlSdrSettings"}, | ||||
|     {"RemoteInput", "remoteInputSettings"}, | ||||
|     {"SDRplay1", "sdrPlaySettings"}, | ||||
|     {"SoapySDR", "soapySDRInputSettings"}, | ||||
|     {"TestSource", "testSourceSettings"}, | ||||
|     {"USRP", "usrpInputSettings"}, | ||||
|     {"XTRX", "XtrxInputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_sourceDeviceHwIdToActionsKey = { | ||||
|     {"Airspy", "airspyActions"}, | ||||
|     {"AirspyHF", "airspyHFActions"}, | ||||
|     {"BladeRF1", "bladeRF1InputActions"}, | ||||
|     {"FCDPro", "fcdProActions"}, | ||||
|     {"FCDPro+", "fcdProPlusActions"}, | ||||
|     {"HackRF", "hackRFInputActions"}, | ||||
|     {"KiwiSDR", "kiwiSDRActions"}, | ||||
|     {"LimeSDR", "limeSdrInputActions"}, | ||||
|     {"LocalInput", "localInputActions"}, | ||||
|     {"Perseus", "perseusActions"}, | ||||
|     {"PlutoSDR", "plutoSdrInputActions"}, | ||||
|     {"RemoteInput", "remoteInputActions"}, | ||||
|     {"RTLSDR", "rtlSdrActions"}, | ||||
|     {"SDRplay1", "sdrPlayActions"}, | ||||
|     {"SoapySDR", "soapySDRInputActions"}, | ||||
|     {"TestSource", "testSourceActions"}, | ||||
|     {"USRP", "usrpSourceActions"}, | ||||
|     {"XTRX", "xtrxInputActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_sinkDeviceHwIdToSettingsKey = { | ||||
|     {"BladeRF1", "bladeRF1OutputSettings"}, | ||||
|     {"BladeRF2", "bladeRF2OutputSettings"}, | ||||
|     {"HackRF", "hackRFOutputSettings"}, | ||||
|     {"LimeSDR", "limeSdrOutputSettings"}, | ||||
|     {"LocalOutput", "localOutputSettings"}, | ||||
|     {"PlutoSDR", "plutoSdrOutputSettings"}, | ||||
|     {"RemoteOutput", "remoteOutputSettings"}, | ||||
|     {"SoapySDR", "soapySDROutputSettings"}, | ||||
|     {"USRP", "usrpOutputSettings"}, | ||||
|     {"XTRX", "xtrxOutputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_sinkDeviceHwIdToActionsKey = { | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToSettingsKey= { | ||||
|     {"BladeRF2", "bladeRF2MIMOSettings"}, | ||||
|     {"TestMI", "testMISettings"}, | ||||
|     {"TestMOSync", "testMOSyncSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToActionsKey= { | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_featureTypeToSettingsKey = { | ||||
|     {"SimplePTT", "SimplePTTSettings"}, | ||||
|     {"RigCtlServer", "RigCtlServerSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_featureTypeToActionsKey = { | ||||
|     {"SimplePTT", "SimplePTTActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIRequestMapper::m_featureURIToSettingsKey = { | ||||
|     {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, | ||||
|     {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"} | ||||
| }; | ||||
| 
 | ||||
| WebAPIRequestMapper::WebAPIRequestMapper(QObject* parent) : | ||||
|     HttpRequestHandler(parent), | ||||
|     m_adapter(0) | ||||
|  | @ -3025,16 +2827,24 @@ bool WebAPIRequestMapper::validateDeviceSettings( | |||
| 
 | ||||
|     if (deviceSettings.getDirection() == 0) // source
 | ||||
|     { | ||||
|         if (m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceSettingsKey = m_sourceDeviceHwIdToSettingsKey[*deviceHwType]; | ||||
|         if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceSettingsKey = WebAPIUtils::m_sourceDeviceHwIdToSettingsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else if (deviceSettings.getDirection() == 1) // sink
 | ||||
|     { | ||||
|         if (m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceSettingsKey = m_sinkDeviceHwIdToSettingsKey[*deviceHwType]; | ||||
|         if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceSettingsKey = WebAPIUtils::m_sinkDeviceHwIdToSettingsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else if (deviceSettings.getDirection() == 2) // MIMO
 | ||||
|     { | ||||
|         if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceSettingsKey = WebAPIUtils::m_mimoDeviceHwIdToSettingsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|  | @ -3069,24 +2879,24 @@ bool WebAPIRequestMapper::validateDeviceActions( | |||
| 
 | ||||
|     if (deviceActions.getDirection() == 0) // source
 | ||||
|     { | ||||
|         if (m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = m_sourceDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         if (WebAPIUtils::m_sourceDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = WebAPIUtils::m_sourceDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else if (deviceActions.getDirection() == 1) // sink
 | ||||
|     { | ||||
|         if (m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = m_sinkDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         if (WebAPIUtils::m_sinkDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = WebAPIUtils::m_sinkDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else if (deviceActions.getDirection() == 2) // MIMO
 | ||||
|     { | ||||
|         if (m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = m_mimoDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         if (WebAPIUtils::m_mimoDeviceHwIdToSettingsKey.contains(*deviceHwType)) { | ||||
|             deviceActionsKey = WebAPIUtils::m_mimoDeviceHwIdToActionsKey[*deviceHwType]; | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|  | @ -3118,8 +2928,8 @@ bool WebAPIRequestMapper::validateChannelSettings( | |||
| 
 | ||||
|     QString *channelType = channelSettings.getChannelType(); | ||||
| 
 | ||||
|     if (m_channelTypeToSettingsKey.contains(*channelType)) { | ||||
|         return getChannelSettings(m_channelTypeToSettingsKey[*channelType], &channelSettings, jsonObject, channelSettingsKeys); | ||||
|     if (WebAPIUtils::m_channelTypeToSettingsKey.contains(*channelType)) { | ||||
|         return getChannelSettings(WebAPIUtils::m_channelTypeToSettingsKey[*channelType], &channelSettings, jsonObject, channelSettingsKeys); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
|  | @ -3144,8 +2954,8 @@ bool WebAPIRequestMapper::validateChannelActions( | |||
| 
 | ||||
|     QString *channelType = channelActions.getChannelType(); | ||||
| 
 | ||||
|     if (m_channelTypeToActionsKey.contains(*channelType)) { | ||||
|         return getChannelActions(m_channelTypeToActionsKey[*channelType], &channelActions, jsonObject, channelActionsKeys); | ||||
|     if (WebAPIUtils::m_channelTypeToActionsKey.contains(*channelType)) { | ||||
|         return getChannelActions(WebAPIUtils::m_channelTypeToActionsKey[*channelType], &channelActions, jsonObject, channelActionsKeys); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
|  | @ -3164,8 +2974,8 @@ bool WebAPIRequestMapper::validateFeatureSettings( | |||
| 
 | ||||
|     QString *featureType = featureSettings.getFeatureType(); | ||||
| 
 | ||||
|     if (m_featureTypeToSettingsKey.contains(*featureType)) { | ||||
|         return getFeatureSettings(m_featureTypeToSettingsKey[*featureType], &featureSettings, jsonObject, featureSettingsKeys); | ||||
|     if (WebAPIUtils::m_featureTypeToSettingsKey.contains(*featureType)) { | ||||
|         return getFeatureSettings(WebAPIUtils::m_featureTypeToSettingsKey[*featureType], &featureSettings, jsonObject, featureSettingsKeys); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
|  | @ -3184,8 +2994,8 @@ bool WebAPIRequestMapper::validateFeatureActions( | |||
| 
 | ||||
|     QString *featureType = featureActions.getFeatureType(); | ||||
| 
 | ||||
|     if (m_featureTypeToActionsKey.contains(*featureType)) { | ||||
|         return getFeatureActions(m_featureTypeToActionsKey[*featureType], &featureActions, jsonObject, featureActionsKeys); | ||||
|     if (WebAPIUtils::m_featureTypeToActionsKey.contains(*featureType)) { | ||||
|         return getFeatureActions(WebAPIUtils::m_featureTypeToActionsKey[*featureType], &featureActions, jsonObject, featureActionsKeys); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
|  | @ -3643,12 +3453,12 @@ bool WebAPIRequestMapper::appendPresetFeatureKeys( | |||
|         feature->setFeatureIdUri(featureURI); | ||||
|         featureKeys.m_keys.append("featureIdURI"); | ||||
| 
 | ||||
|         if (featureSettingsJson.contains("config") && m_featureURIToSettingsKey.contains(*featureURI)) | ||||
|         if (featureSettingsJson.contains("config") && WebAPIUtils::m_featureURIToSettingsKey.contains(*featureURI)) | ||||
|         { | ||||
|             SWGSDRangel::SWGFeatureSettings *featureSettings = new SWGSDRangel::SWGFeatureSettings(); | ||||
|             feature->setConfig(featureSettings); | ||||
|             return getFeatureSettings( | ||||
|                 m_channelURIToSettingsKey[*featureURI], | ||||
|                 WebAPIUtils::m_channelURIToSettingsKey[*featureURI], | ||||
|                 featureSettings, | ||||
|                 featureSettingsJson["config"].toObject(), | ||||
|                 featureKeys.m_featureKeys | ||||
|  | @ -3677,11 +3487,11 @@ bool WebAPIRequestMapper::appendPresetChannelKeys( | |||
|         channel->setChannelIdUri(channelURI); | ||||
|         channelKeys.m_keys.append("channelIdURI"); | ||||
| 
 | ||||
|         if (channelSettingsJson.contains("config") && m_channelURIToSettingsKey.contains(*channelURI)) | ||||
|         if (channelSettingsJson.contains("config") && WebAPIUtils::m_channelURIToSettingsKey.contains(*channelURI)) | ||||
|         { | ||||
|             SWGSDRangel::SWGChannelSettings *channelSettings = new SWGSDRangel::SWGChannelSettings(); | ||||
|             channel->setConfig(channelSettings); | ||||
|             return getChannelSettings(m_channelURIToSettingsKey[*channelURI], channelSettings, channelSettingsJson["config"].toObject(), channelKeys.m_channelKeys); | ||||
|             return getChannelSettings(WebAPIUtils::m_channelURIToSettingsKey[*channelURI], channelSettings, channelSettingsJson["config"].toObject(), channelKeys.m_channelKeys); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  | @ -3933,11 +3743,11 @@ bool WebAPIRequestMapper::appendPresetDeviceKeys( | |||
|             devicelKeys.m_keys.append("deviceSequence"); | ||||
|         } | ||||
| 
 | ||||
|         if (deviceSettngsJson.contains("config") && m_deviceIdToSettingsKey.contains(*deviceId)) | ||||
|         if (deviceSettngsJson.contains("config") && WebAPIUtils::m_deviceIdToSettingsKey.contains(*deviceId)) | ||||
|         { | ||||
|             SWGSDRangel::SWGDeviceSettings *deviceSettings = new SWGSDRangel::SWGDeviceSettings(); | ||||
|             device->setConfig(deviceSettings); | ||||
|             return getDeviceSettings(m_deviceIdToSettingsKey[*deviceId], deviceSettings, deviceSettngsJson["config"].toObject(), devicelKeys.m_deviceKeys); | ||||
|             return getDeviceSettings(WebAPIUtils::m_deviceIdToSettingsKey[*deviceId], deviceSettings, deviceSettngsJson["config"].toObject(), devicelKeys.m_deviceKeys); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|  |  | |||
|  | @ -21,6 +21,224 @@ | |||
| 
 | ||||
| #include "webapiutils.h" | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = { | ||||
|     {"sdrangel.channel.amdemod", "AMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.am", "AMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modam", "AMModSettings"}, | ||||
|     {"sdrangel.channeltx.modatv", "ATVModSettings"}, | ||||
|     {"sdrangel.channel.bfm", "BFMDemodSettings"}, | ||||
|     {"sdrangel.channel.chanalyzer", "ChannelAnalyzerSettings"}, | ||||
|     {"sdrangel.channel.chanalyzerng", "ChannelAnalyzerSettings"}, // remap
 | ||||
|     {"org.f4exb.sdrangelove.channel.chanalyzer", "ChannelAnalyzerSettings"}, // remap
 | ||||
|     {"sdrangel.channel.chirpchatdemod", "ChirpChatDemodSettings"}, | ||||
|     {"sdrangel.channel.modchirpchat", "ChirpChatModSettings"}, | ||||
|     {"sdrangel.channel.demodatv", "ATVDemodSettings"}, | ||||
|     {"sdrangel.channel.demoddatv", "DATVDemodSettings"}, | ||||
|     {"sdrangel.channel.dsddemod", "DSDDemodSettings"}, | ||||
|     {"sdrangel.channel.filesink", "FileSinkSettings"}, | ||||
|     {"sdrangel.channeltx.filesource", "FileSourceSettings"}, | ||||
|     {"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"}, | ||||
|     {"sdrangel.channeltx.freedvmod", "FreeDVModSettings"}, | ||||
|     {"sdrangel.channel.freqtracker", "FreqTrackerSettings"}, | ||||
|     {"sdrangel.channel.nfmdemod", "NFMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modnfm", "NFMModSettings"}, | ||||
|     {"sdrangel.demod.localsink", "LocalSinkSettings"}, | ||||
|     {"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap
 | ||||
|     {"sdrangel.channel.localsource", "LocalSourceSettings"}, | ||||
|     {"sdrangel.channeltx.modpacket", "PacketModSettings"}, | ||||
|     {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, | ||||
|     {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, | ||||
|     {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, | ||||
|     {"sdrangel.channeltx.modssb", "SSBModSettings"}, | ||||
|     {"sdrangel.channel.ssbdemod", "SSBDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.ssb", "SSBDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.udpsource", "UDPSourceSettings"}, | ||||
|     {"sdrangel.channeltx.udpsink", "UDPSourceSettings"}, // remap
 | ||||
|     {"sdrangel.channel.udpsink", "UDPSinkSettings"}, | ||||
|     {"sdrangel.channel.udpsrc", "UDPSinkSettings"}, // remap
 | ||||
|     {"sdrangel.channel.wfmdemod", "WFMDemodSettings"}, | ||||
|     {"de.maintech.sdrangelove.channel.wfm", "WFMDemodSettings"}, // remap
 | ||||
|     {"sdrangel.channeltx.modwfm", "WFMModSettings"}, | ||||
|     {"sdrangel.channel.beamsteeringcwmod", "BeamSteeringCWModSettings"}, | ||||
|     {"sdrangel.channelmimo.interferometer", "InterferometerSettings"}, | ||||
|     {"sdrangel.channel.sigmffilesink", "SigMFFileSinkSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_deviceIdToSettingsKey = { | ||||
|     {"sdrangel.samplesource.airspy", "airspySettings"}, | ||||
|     {"sdrangel.samplesource.airspyhf", "airspyHFSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf1input", "bladeRF1InputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf", "bladeRF1InputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesink.bladerf1output", "bladeRF1OutputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf1output", "bladeRF1OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.bladerfoutput", "bladeRF1OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.bladerf2input", "bladeRF2InputSettings"}, | ||||
|     {"sdrangel.samplesink.bladerf2output", "bladeRF2OutputSettings"}, | ||||
|     {"sdrangel.samplesource.bladerf2output", "bladeRF2OutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplemimo.bladerf2mimo", "bladeRF2MIMOSettings"}, | ||||
|     {"sdrangel.samplesource.fcdpro", "fcdProSettings"}, | ||||
|     {"sdrangel.samplesource.fcdproplus", "fcdProPlusSettings"}, | ||||
|     {"sdrangel.samplesource.fileinput", "fileInputSettings"}, | ||||
|     {"sdrangel.samplesource.filesource", "fileInputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.hackrf", "hackRFInputSettings"}, | ||||
|     {"sdrangel.samplesink.hackrf", "hackRFOutputSettings"}, | ||||
|     {"sdrangel.samplesource.hackrfoutput", "hackRFOutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplesource.kiwisdrsource", "kiwiSDRSettings"}, | ||||
|     {"sdrangel.samplesource.limesdr", "limeSdrInputSettings"}, | ||||
|     {"sdrangel.samplesink.limesdr", "limeSdrOutputSettings"}, | ||||
|     {"sdrangel.samplesource.localinput", "localInputSettings"}, | ||||
|     {"sdrangel.samplesink.localoutput", "localOutputSettings"}, | ||||
|     {"sdrangel.samplesource.localoutput", "localOutputSettings"}, // remap
 | ||||
|     {"sdrangel.samplemimo.metismiso", "metisMISOSettings"}, | ||||
|     {"sdrangel.samplesource.perseus", "perseusSettings"}, | ||||
|     {"sdrangel.samplesource.plutosdr", "plutoSdrInputSettings"}, | ||||
|     {"sdrangel.samplesink.plutosdr", "plutoSdrOutputSettings"}, | ||||
|     {"sdrangel.samplesource.rtlsdr", "rtlSdrSettings"}, | ||||
|     {"sdrangel.samplesource.remoteinput", "remoteInputSettings"}, | ||||
|     {"sdrangel.samplesink.remoteoutput", "remoteOutputSettings"}, | ||||
|     {"sdrangel.samplesource.sdrplay", "sdrPlaySettings"}, | ||||
|     {"sdrangel.samplesource.sigmffileinput", "sigMFFileInputSettings"}, | ||||
|     {"sdrangel.samplesource.soapysdrinput", "soapySDRInputSettings"}, | ||||
|     {"sdrangel.samplesink.soapysdroutput", "soapySDROutputSettings"}, | ||||
|     {"sdrangel.samplesource.testsource", "testSourceSettings"}, | ||||
|     {"sdrangel.samplemimo.testmi", "testMISettings"}, | ||||
|     {"sdrangel.samplemimo.testmosync", "testMOSyncSettings"}, | ||||
|     {"sdrangel.samplesource.usrp", "usrpInputSettings"}, | ||||
|     {"sdrangel.samplesink.usrp", "usrpOutputSettings"}, | ||||
|     {"sdrangel.samplesource.xtrx", "xtrxInputSettings"}, | ||||
|     {"sdrangel.samplesink.xtrx", "xtrxOutputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = { | ||||
|     {"AMDemod", "AMDemodSettings"}, | ||||
|     {"AMMod", "AMModSettings"}, | ||||
|     {"ATVDemod", "ATVDemodSettings"}, | ||||
|     {"ATVMod", "ATVModSettings"}, | ||||
|     {"BFMDemod", "BFMDemodSettings"}, | ||||
|     {"ChannelAnalyzer", "ChannelAnalyzerSettings"}, | ||||
|     {"ChirpChatDemod", "ChirpChatDemodSettings"}, | ||||
|     {"ChirpChatMod", "ChirpChatModSettings"}, | ||||
|     {"DATVDemod", "DATVDemodSettings"}, | ||||
|     {"DSDDemod", "DSDDemodSettings"}, | ||||
|     {"FileSink", "FileSinkSettings"}, | ||||
|     {"FileSource", "FileSourceSettings"}, | ||||
|     {"FreeDVDemod", "FreeDVDemodSettings"}, | ||||
|     {"FreeDVMod", "FreeDVModSettings"}, | ||||
|     {"FreqTracker", "FreqTrackerSettings"}, | ||||
|     {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"}, | ||||
|     {"NFMDemod", "NFMDemodSettings"}, | ||||
|     {"NFMMod", "NFMModSettings"}, | ||||
|     {"PacketMod", "PacketModSettings"}, | ||||
|     {"LocalSink", "LocalSinkSettings"}, | ||||
|     {"LocalSource", "LocalSourceSettings"}, | ||||
|     {"RemoteSink", "RemoteSinkSettings"}, | ||||
|     {"RemoteSource", "RemoteSourceSettings"}, | ||||
|     {"SSBMod", "SSBModSettings"}, | ||||
|     {"SSBDemod", "SSBDemodSettings"}, | ||||
|     {"UDPSink", "UDPSourceSettings"}, | ||||
|     {"UDPSource", "UDPSinkSettings"}, | ||||
|     {"WFMDemod", "WFMDemodSettings"}, | ||||
|     {"WFMMod", "WFMModSettings"}, | ||||
|     {"BeamSteeringCWMod", "BeamSteeringCWModSettings"}, | ||||
|     {"Interferometer", "InterferometerSettings"}, | ||||
|     {"SigMFFileSink", "SigMFFileSinkSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_channelTypeToActionsKey = { | ||||
|     {"FileSink", "FileSinkActions"}, | ||||
|     {"FileSource", "FileSourceActions"}, | ||||
|     {"SigMFFileSink", "SigMFFileSinkActions"}, | ||||
|     {"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModActions"}, | ||||
|     {"PacketMod", "PacketModActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_sourceDeviceHwIdToSettingsKey = { | ||||
|     {"Airspy", "airspySettings"}, | ||||
|     {"AirspyHF", "airspyHFSettings"}, | ||||
|     {"BladeRF1", "bladeRF1InputSettings"}, | ||||
|     {"BladeRF2", "bladeRF2InputSettings"}, | ||||
|     {"FCDPro", "fcdProSettings"}, | ||||
|     {"FCDPro+", "fcdProPlusSettings"}, | ||||
|     {"FileInput", "fileInputSettings"}, | ||||
|     {"HackRF", "hackRFInputSettings"}, | ||||
|     {"KiwiSDR", "kiwiSDRSettings"}, | ||||
|     {"LimeSDR", "limeSdrInputSettings"}, | ||||
|     {"LocalInput", "localInputSettings"}, | ||||
|     {"Perseus", "perseusSettings"}, | ||||
|     {"PlutoSDR", "plutoSdrInputSettings"}, | ||||
|     {"RTLSDR", "rtlSdrSettings"}, | ||||
|     {"RemoteInput", "remoteInputSettings"}, | ||||
|     {"SDRplay1", "sdrPlaySettings"}, | ||||
|     {"SigMFFileInput", "sigMFFileInputSettings"}, | ||||
|     {"SoapySDR", "soapySDRInputSettings"}, | ||||
|     {"TestSource", "testSourceSettings"}, | ||||
|     {"USRP", "usrpInputSettings"}, | ||||
|     {"XTRX", "xtrxInputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_sourceDeviceHwIdToActionsKey = { | ||||
|     {"Airspy", "airspyActions"}, | ||||
|     {"AirspyHF", "airspyHFActions"}, | ||||
|     {"BladeRF1", "bladeRF1InputActions"}, | ||||
|     {"FCDPro", "fcdProActions"}, | ||||
|     {"FCDPro+", "fcdProPlusActions"}, | ||||
|     {"HackRF", "hackRFInputActions"}, | ||||
|     {"KiwiSDR", "kiwiSDRActions"}, | ||||
|     {"LimeSDR", "limeSdrInputActions"}, | ||||
|     {"LocalInput", "localInputActions"}, | ||||
|     {"Perseus", "perseusActions"}, | ||||
|     {"PlutoSDR", "plutoSdrInputActions"}, | ||||
|     {"RemoteInput", "remoteInputActions"}, | ||||
|     {"RTLSDR", "rtlSdrActions"}, | ||||
|     {"SDRplay1", "sdrPlayActions"}, | ||||
|     {"SigMFFileInput", "sigMFFileActions"}, | ||||
|     {"SoapySDR", "soapySDRInputActions"}, | ||||
|     {"TestSource", "testSourceActions"}, | ||||
|     {"USRP", "usrpSourceActions"}, | ||||
|     {"XTRX", "xtrxInputActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_sinkDeviceHwIdToSettingsKey = { | ||||
|     {"BladeRF1", "bladeRF1OutputSettings"}, | ||||
|     {"BladeRF2", "bladeRF2OutputSettings"}, | ||||
|     {"HackRF", "hackRFOutputSettings"}, | ||||
|     {"LimeSDR", "limeSdrOutputSettings"}, | ||||
|     {"LocalOutput", "localOutputSettings"}, | ||||
|     {"PlutoSDR", "plutoSdrOutputSettings"}, | ||||
|     {"RemoteOutput", "remoteOutputSettings"}, | ||||
|     {"SoapySDR", "soapySDROutputSettings"}, | ||||
|     {"USRP", "usrpOutputSettings"}, | ||||
|     {"XTRX", "xtrxOutputSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_sinkDeviceHwIdToActionsKey = { | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToSettingsKey = { | ||||
|     {"BladeRF2", "bladeRF2MIMOSettings"}, | ||||
|     {"MetisMISO", "metisMISOSettings"}, | ||||
|     {"TestMI", "testMISettings"}, | ||||
|     {"TestMOSync", "testMOSyncSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToActionsKey = { | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_featureTypeToSettingsKey = { | ||||
|     {"SimplePTT", "SimplePTTSettings"}, | ||||
|     {"RigCtlServer", "RigCtlServerSettings"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_featureTypeToActionsKey = { | ||||
|     {"SimplePTT", "SimplePTTActions"} | ||||
| }; | ||||
| 
 | ||||
| const QMap<QString, QString> WebAPIUtils::m_featureURIToSettingsKey = { | ||||
|     {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, | ||||
|     {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"} | ||||
| }; | ||||
| 
 | ||||
| // Get integer value from within JSON object
 | ||||
| bool WebAPIUtils::getObjectInt(const QJsonObject &json, const QString &key, int &value) | ||||
| { | ||||
|  | @ -114,3 +332,193 @@ bool WebAPIUtils::setSubObjectDouble(QJsonObject &json, const QString &key, doub | |||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // look for value in key=value
 | ||||
| bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         value = json[key]; | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (extractValue(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // look for [...] in key=[...]
 | ||||
| bool WebAPIUtils::extractArray(const QJsonObject &json, const QString &key, QJsonArray &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         if (json[key].isArray()) | ||||
|         { | ||||
|             value = json[key].toArray(); | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (extractArray(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // look for {...} in key={...}
 | ||||
| bool WebAPIUtils::extractObject(const QJsonObject &json, const QString &key, QJsonObject &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         if (json[key].isObject()) | ||||
|         { | ||||
|             value = json[key].toObject(); | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (extractObject(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // set value in key=value
 | ||||
| bool WebAPIUtils::setValue(const QJsonObject &json, const QString &key, const QJsonValue &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         json[key] = value; | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (setValue(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // set [...] in key=[...]
 | ||||
| bool WebAPIUtils::setArray(const QJsonObject &json, const QString &key, const QJsonArray &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         if (json[key].isArray()) | ||||
|         { | ||||
|             json[key] = value; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (setArray(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // set {...} in key={...}
 | ||||
| bool WebAPIUtils::setObject(const QJsonObject &json, const QString &key, const QJsonObject &value) | ||||
| { | ||||
|     // final
 | ||||
|     if (json.contains(key)) | ||||
|     { | ||||
|         if (json[key].isObject()) | ||||
|         { | ||||
|             json[key] = value; | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         for (QJsonObject::const_iterator  it = json.begin(); it != json.end(); it++) | ||||
|         { | ||||
|             QJsonValue jsonValue = it.value(); | ||||
| 
 | ||||
|             if (jsonValue.isObject()) | ||||
|             { | ||||
|                 if (setObject(jsonValue.toObject(), key, value)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
|  |  | |||
|  | @ -21,17 +21,38 @@ | |||
| 
 | ||||
| #include <QJsonObject> | ||||
| #include <QString> | ||||
| #include <QMap> | ||||
| 
 | ||||
| #include "export.h" | ||||
| 
 | ||||
| class SDRBASE_API WebAPIUtils | ||||
| { | ||||
| public: | ||||
|     static const QMap<QString, QString> m_channelURIToSettingsKey; | ||||
|     static const QMap<QString, QString> m_deviceIdToSettingsKey; | ||||
|     static const QMap<QString, QString> m_channelTypeToSettingsKey; | ||||
|     static const QMap<QString, QString> m_sourceDeviceHwIdToSettingsKey; | ||||
|     static const QMap<QString, QString> m_sinkDeviceHwIdToSettingsKey; | ||||
|     static const QMap<QString, QString> m_mimoDeviceHwIdToSettingsKey; | ||||
|     static const QMap<QString, QString> m_channelTypeToActionsKey; | ||||
|     static const QMap<QString, QString> m_sourceDeviceHwIdToActionsKey; | ||||
|     static const QMap<QString, QString> m_sinkDeviceHwIdToActionsKey; | ||||
|     static const QMap<QString, QString> m_mimoDeviceHwIdToActionsKey; | ||||
|     static const QMap<QString, QString> m_featureTypeToSettingsKey; | ||||
|     static const QMap<QString, QString> m_featureTypeToActionsKey; | ||||
|     static const QMap<QString, QString> m_featureURIToSettingsKey; | ||||
| 
 | ||||
|     static bool getObjectInt(const QJsonObject &json, const QString &key, int &value); | ||||
|     static bool getObjectString(const QJsonObject &json, const QString &key, QString &value); | ||||
|     static bool getObjectObjects(const QJsonObject &json, const QString &key, QList<QJsonObject> &objects); | ||||
|     static bool getSubObjectDouble(const QJsonObject &json, const QString &key, double &value); | ||||
|     static bool setSubObjectDouble(QJsonObject &json, const QString &key, double value); | ||||
|     static bool extractValue(const QJsonObject &json, const QString &key, QJsonValue &value); | ||||
|     static bool extractArray(const QJsonObject &json, const QString &key, QJsonArray &value); | ||||
|     static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value); | ||||
|     static bool setValue(const QJsonObject &json, const QString &key, const QJsonValue &value); | ||||
|     static bool setArray(const QJsonObject &json, const QString &key, const QJsonArray &value); | ||||
|     static bool setObject(const QJsonObject &json, const QString &key, const QJsonObject &value); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 f4exb
						f4exb