From 79b087e93cddfd3d5ed9d93144095270599ce6c1 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 29 Sep 2020 01:14:44 +0200 Subject: [PATCH] Feature plugins: REST API fixes --- sdrbase/webapi/webapiadapterinterface.cpp | 10 +- sdrbase/webapi/webapiadapterinterface.h | 197 ++++++++ sdrbase/webapi/webapirequestmapper.cpp | 524 +++++++++++++++++++++- sdrbase/webapi/webapirequestmapper.h | 13 + 4 files changed, 742 insertions(+), 2 deletions(-) diff --git a/sdrbase/webapi/webapiadapterinterface.cpp b/sdrbase/webapi/webapiadapterinterface.cpp index 850fff7f5..89ffce35d 100644 --- a/sdrbase/webapi/webapiadapterinterface.cpp +++ b/sdrbase/webapi/webapiadapterinterface.cpp @@ -57,6 +57,14 @@ std::regex WebAPIAdapterInterface::devicesetChannelSettingsURLRe("^/sdrangel/dev std::regex WebAPIAdapterInterface::devicesetChannelReportURLRe("^/sdrangel/deviceset/([0-9]{1,2})/channel/([0-9]{1,2})/report"); std::regex WebAPIAdapterInterface::devicesetChannelActionsURLRe("^/sdrangel/deviceset/([0-9]{1,2})/channel/([0-9]{1,2})/actions"); +std::regex WebAPIAdapterInterface::featuresetURLRe("^/sdrangel/featureset/([0-9]{1,2})$"); +std::regex WebAPIAdapterInterface::featuresetFeatureURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature$"); +std::regex WebAPIAdapterInterface::featuresetFeatureIndexURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature/([0-9]{1,2})$"); +std::regex WebAPIAdapterInterface::featuresetFeatureRunURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature/([0-9]{1,2})/run$"); +std::regex WebAPIAdapterInterface::featuresetFeatureSettingsURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature/([0-9]{1,2})/settings$"); +std::regex WebAPIAdapterInterface::featuresetFeatureReportURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature/([0-9]{1,2})/report"); +std::regex WebAPIAdapterInterface::featuresetFeatureActionsURLRe("^/sdrangel/featureset/([0-9]{1,2})/feature/([0-9]{1,2})/actions"); + void WebAPIAdapterInterface::ConfigKeys::debug() const { qDebug("WebAPIAdapterInterface::ConfigKeys::debug"); @@ -162,4 +170,4 @@ void WebAPIAdapterInterface::ConfigKeys::debug() const } qDebug(" }"); } -} \ No newline at end of file +} diff --git a/sdrbase/webapi/webapiadapterinterface.h b/sdrbase/webapi/webapiadapterinterface.h index 73c4de8a0..bdef0205f 100644 --- a/sdrbase/webapi/webapiadapterinterface.h +++ b/sdrbase/webapi/webapiadapterinterface.h @@ -1035,6 +1035,196 @@ public: return 501; } + /** + * Handler of /sdrangel/featureset/{featuresetIndex} (GET) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetGet( + int deviceSetIndex, + SWGSDRangel::SWGFeatureSet& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) deviceSetIndex; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature (POST) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeaturePost( + int featureSetIndex, + SWGSDRangel::SWGFeatureSettings& query, + SWGSDRangel::SWGSuccessResponse& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) query; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/run (GET) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureDelete( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGSuccessResponse& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + (void) error; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/run (GET) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureRunGet( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGDeviceState& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + (void) error; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/run (POST) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureRunPost( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGDeviceState& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + (void) error; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/run (DELETE) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureRunDelete( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGDeviceState& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + (void) error; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/settings (GET) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureSettingsGet( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGFeatureSettings& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/settings (PUT, PATCH) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureSettingsPutPatch( + int featureSetIndex, + int featureIndex, + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) force; + (void) featureSettingsKeys; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/report (GET) + * returns the Http status code (default 501: not implemented) + */ + virtual int featuresetFeatureReportGet( + int featureSetIndex, + int featureIndex, + SWGSDRangel::SWGFeatureReport& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/featureset/{featuresetIndex}/feature/{featureIndex}/actions (POST) + * posts an action on the channel (default 501: not implemented) + */ + virtual int featuresetFeatureActionsPost( + int featureSetIndex, + int featureIndex, + const QStringList& featureActionsKeys, + SWGSDRangel::SWGFeatureActions& query, + SWGSDRangel::SWGSuccessResponse& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) featureSetIndex; + (void) featureIndex; + (void) featureActionsKeys; + (void) query; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + static QString instanceSummaryURL; static QString instanceConfigURL; static QString instanceDevicesURL; @@ -1071,6 +1261,13 @@ public: static std::regex devicesetChannelReportURLRe; static std::regex devicesetChannelActionsURLRe; static std::regex devicesetChannelsReportURLRe; + static std::regex featuresetURLRe; + static std::regex featuresetFeatureURLRe; + static std::regex featuresetFeatureIndexURLRe; + static std::regex featuresetFeatureRunURLRe; + static std::regex featuresetFeatureSettingsURLRe; + static std::regex featuresetFeatureReportURLRe; + static std::regex featuresetFeatureActionsURLRe; }; diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index d7f32faba..efff5fd59 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -233,8 +233,18 @@ const QMap WebAPIRequestMapper::m_mimoDeviceHwIdToSettingsKey= const QMap WebAPIRequestMapper::m_mimoDeviceHwIdToActionsKey= { }; +const QMap WebAPIRequestMapper::m_featureTypeToSettingsKey = { + {"SimplePTT", "SimplePTTSettings"}, + {"RigCtlServer", "RigCtlServerSettings"} +}; + +const QMap WebAPIRequestMapper::m_featureTypeToActionsKey = { + {"SimplePTT", "SimplePTTActions"} +}; + const QMap WebAPIRequestMapper::m_featureURIToSettingsKey = { - {"sdrangel.feature.simpleptt", "SimplePTTSettings"} + {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, + {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"} }; WebAPIRequestMapper::WebAPIRequestMapper(QObject* parent) : @@ -363,6 +373,20 @@ void WebAPIRequestMapper::service(qtwebapp::HttpRequest& request, qtwebapp::Http devicesetChannelReportService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::devicesetChannelActionsURLRe)) { devicesetChannelActionsService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetURLRe)) { + featuresetService(std::string(desc_match[1]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureURLRe)) { + featuresetFeatureService(std::string(desc_match[1]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureIndexURLRe)) { + featuresetFeatureIndexService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureRunURLRe)) { + featuresetFeatureRunService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureSettingsURLRe)) { + featuresetFeatureSettingsService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureReportURLRe)) { + featuresetFeatureReportService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); + } else if (std::regex_match(pathStr, desc_match, WebAPIAdapterInterface::featuresetFeatureActionsURLRe)) { + featuresetFeatureActionsService(std::string(desc_match[1]), std::string(desc_match[2]), request, response); } else // serve static documentation pages { @@ -2410,6 +2434,443 @@ void WebAPIRequestMapper::devicesetChannelActionsService( } } +void WebAPIRequestMapper::featuresetService(const std::string& indexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + if (request.getMethod() == "GET") + { + try + { + SWGSDRangel::SWGFeatureSet normalResponse; + int deviceSetIndex = boost::lexical_cast(indexStr); + int status = m_adapter->featuresetGet(deviceSetIndex, normalResponse, errorResponse); + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on device set index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureService( + const std::string& featureSetIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + + if (request.getMethod() == "POST") + { + QString jsonStr = request.getBody(); + QJsonObject jsonObject; + + if (parseJsonBody(jsonStr, jsonObject, response)) + { + SWGSDRangel::SWGFeatureSettings query; + SWGSDRangel::SWGSuccessResponse normalResponse; + resetFeatureSettings(query); + + if (jsonObject.contains("featureType") && jsonObject["featureType"].isString()) + { + query.setFeatureType(new QString(jsonObject["featureType"].toString())); + + int status = m_adapter->featuresetFeaturePost(featureSetIndex, query, normalResponse, errorResponse); + + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON request"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON request"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON format"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON format"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureIndexService( + const std::string& featureSetIndexStr, + const std::string& featureIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + int featureIndex = boost::lexical_cast(featureIndexStr); + + if (request.getMethod() == "DELETE") + { + SWGSDRangel::SWGSuccessResponse normalResponse; + int status = m_adapter->featuresetFeatureDelete(featureSetIndex, featureIndex, normalResponse, errorResponse); + + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureRunService( + const std::string& featureSetIndexStr, + const std::string& featureIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + int featureIndex = boost::lexical_cast(featureIndexStr); + + if (request.getMethod() == "GET") + { + SWGSDRangel::SWGDeviceState normalResponse; + int status = m_adapter->featuresetFeatureRunGet(featureSetIndex, featureIndex, normalResponse, errorResponse); + + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else if (request.getMethod() == "POST") + { + SWGSDRangel::SWGDeviceState normalResponse; + int status = m_adapter->featuresetFeatureRunPost(featureSetIndex, featureIndex, normalResponse, errorResponse); + + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + + } + else if (request.getMethod() == "DELETE") + { + SWGSDRangel::SWGDeviceState normalResponse; + int status = m_adapter->featuresetFeatureRunDelete(featureSetIndex, featureIndex, normalResponse, errorResponse); + + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureSettingsService( + const std::string& featureSetIndexStr, + const std::string& featureIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + int featureIndex = boost::lexical_cast(featureIndexStr); + + if (request.getMethod() == "GET") + { + SWGSDRangel::SWGFeatureSettings normalResponse; + resetFeatureSettings(normalResponse); + int status = m_adapter->featuresetFeatureSettingsGet(featureSetIndex, featureIndex, normalResponse, errorResponse); + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else if ((request.getMethod() == "PUT") || (request.getMethod() == "PATCH")) + { + QString jsonStr = request.getBody(); + QJsonObject jsonObject; + + if (parseJsonBody(jsonStr, jsonObject, response)) + { + SWGSDRangel::SWGFeatureSettings normalResponse; + resetFeatureSettings(normalResponse); + QStringList featureSettingsKeys; + + if (validateFeatureSettings(normalResponse, jsonObject, featureSettingsKeys)) + { + int status = m_adapter->featuresetFeatureSettingsPutPatch( + featureSetIndex, + featureIndex, + (request.getMethod() == "PUT"), // force settings on PUT + featureSettingsKeys, + normalResponse, + errorResponse); + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON request"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON request"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON format"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON format"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureReportService( + const std::string& featureSetIndexStr, + const std::string& featureIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + int featureIndex = boost::lexical_cast(featureIndexStr); + + if (request.getMethod() == "GET") + { + SWGSDRangel::SWGFeatureReport normalResponse; + resetFeatureReport(normalResponse); + int status = m_adapter->featuresetFeatureReportGet(featureSetIndex, featureIndex, normalResponse, errorResponse); + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch (const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + +void WebAPIRequestMapper::featuresetFeatureActionsService( + const std::string& featureSetIndexStr, + const std::string& featureIndexStr, + qtwebapp::HttpRequest& request, + qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + try + { + int featureSetIndex = boost::lexical_cast(featureSetIndexStr); + int featureIndex = boost::lexical_cast(featureIndexStr); + + if (request.getMethod() == "POST") + { + QString jsonStr = request.getBody(); + QJsonObject jsonObject; + + if (parseJsonBody(jsonStr, jsonObject, response)) + { + SWGSDRangel::SWGFeatureActions query; + SWGSDRangel::SWGSuccessResponse normalResponse; + resetFeatureActions(query); + QStringList featureActionsKeys; + + if (validateFeatureActions(query, jsonObject, featureActionsKeys)) + { + int status = m_adapter->featuresetFeatureActionsPost( + featureSetIndex, + featureIndex, + featureActionsKeys, + query, + normalResponse, + errorResponse); + response.setStatus(status); + + if (status/100 == 2) { + response.write(normalResponse.asJson().toUtf8()); + } else { + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON request"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON request"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(400,"Invalid JSON format"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON format"; + response.write(errorResponse.asJson().toUtf8()); + } + } + else + { + response.setStatus(405,"Invalid HTTP method"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid HTTP method"; + response.write(errorResponse.asJson().toUtf8()); + } + } + catch(const boost::bad_lexical_cast &e) + { + errorResponse.init(); + *errorResponse.getMessage() = "Wrong integer conversion on index"; + response.setStatus(400,"Invalid data"); + response.write(errorResponse.asJson().toUtf8()); + } +} + bool WebAPIRequestMapper::parseJsonBody(QString& jsonStr, QJsonObject& jsonObject, qtwebapp::HttpResponse& response) { SWGSDRangel::SWGErrorResponse errorResponse; @@ -2682,6 +3143,46 @@ bool WebAPIRequestMapper::validateChannelActions( } } +bool WebAPIRequestMapper::validateFeatureSettings( + SWGSDRangel::SWGFeatureSettings& featureSettings, + QJsonObject& jsonObject, + QStringList& featureSettingsKeys) +{ + if (jsonObject.contains("featureType") && jsonObject["featureType"].isString()) { + featureSettings.setFeatureType(new QString(jsonObject["featureType"].toString())); + } else { + return false; + } + + QString *featureType = featureSettings.getFeatureType(); + + if (m_featureTypeToSettingsKey.contains(*featureType)) { + return getFeatureSettings(m_featureTypeToSettingsKey[*featureType], &featureSettings, jsonObject, featureSettingsKeys); + } else { + return false; + } +} + +bool WebAPIRequestMapper::validateFeatureActions( + SWGSDRangel::SWGFeatureActions& featureActions, + QJsonObject& jsonObject, + QStringList& featureActionsKeys) +{ + if (jsonObject.contains("featureType") && jsonObject["featureType"].isString()) { + featureActions.setFeatureType(new QString(jsonObject["featureType"].toString())); + } else { + return false; + } + + QString *featureType = featureActions.getFeatureType(); + + if (m_featureTypeToActionsKey.contains(*featureType)) { + return getFeatureActions(m_featureTypeToActionsKey[*featureType], &featureActions, jsonObject, featureActionsKeys); + } else { + return false; + } +} + bool WebAPIRequestMapper::validateAudioInputDevice( SWGSDRangel::SWGAudioInputDevice& audioInputDevice, QJsonObject& jsonObject, @@ -3852,6 +4353,27 @@ void WebAPIRequestMapper::resetAudioOutputDevice(SWGSDRangel::SWGAudioOutputDevi audioOutputDevice.setUdpAddress(nullptr); } +void WebAPIRequestMapper::resetFeatureSettings(SWGSDRangel::SWGFeatureSettings& featureSettings) +{ + featureSettings.cleanup(); + featureSettings.setFeatureType(nullptr); + featureSettings.setSimplePttSettings(nullptr); +} + +void WebAPIRequestMapper::resetFeatureReport(SWGSDRangel::SWGFeatureReport& featureReport) +{ + featureReport.cleanup(); + featureReport.setFeatureType(nullptr); + featureReport.setSimplePttReport(nullptr); +} + +void WebAPIRequestMapper::resetFeatureActions(SWGSDRangel::SWGFeatureActions& featureActions) +{ + featureActions.cleanup(); + featureActions.setFeatureType(nullptr); + featureActions.setSimplePttActions(nullptr); +} + void WebAPIRequestMapper::processChannelAnalyzerSettings( SWGSDRangel::SWGChannelSettings *channelSettings, const QJsonObject& channelSettingsJson, diff --git a/sdrbase/webapi/webapirequestmapper.h b/sdrbase/webapi/webapirequestmapper.h index 7a252b5bb..fcd10246a 100644 --- a/sdrbase/webapi/webapirequestmapper.h +++ b/sdrbase/webapi/webapirequestmapper.h @@ -93,6 +93,14 @@ private: void devicesetChannelReportService(const std::string& deviceSetIndexStr, const std::string& channelIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void devicesetChannelActionsService(const std::string& deviceSetIndexStr, const std::string& channelIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetService(const std::string& indexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureService(const std::string& indexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureIndexService(const std::string& featureSetIndexStr, const std::string& featureIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureRunService(const std::string& featureSetIndexStr, const std::string& featureIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureSettingsService(const std::string& featureSetIndexStr, const std::string& featureIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureReportService(const std::string& featureSetIndexStr, const std::string& featureIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void featuresetFeatureActionsService(const std::string& featureSetIndexStr, const std::string& featureIndexStr, qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + bool validatePresetTransfer(SWGSDRangel::SWGPresetTransfer& presetTransfer); bool validatePresetIdentifer(SWGSDRangel::SWGPresetIdentifier& presetIdentifier); bool validatePresetExport(SWGSDRangel::SWGPresetExport& presetExport); @@ -101,6 +109,8 @@ private: bool validateDeviceActions(SWGSDRangel::SWGDeviceActions& deviceActions, QJsonObject& jsonObject, QStringList& deviceActionsKeys); bool validateChannelSettings(SWGSDRangel::SWGChannelSettings& channelSettings, QJsonObject& jsonObject, QStringList& channelSettingsKeys); bool validateChannelActions(SWGSDRangel::SWGChannelActions& channelActions, QJsonObject& jsonObject, QStringList& channelActionsKeys); + bool validateFeatureSettings(SWGSDRangel::SWGFeatureSettings& featureSettings, QJsonObject& jsonObject, QStringList& featureSettingsKeys); + bool validateFeatureActions(SWGSDRangel::SWGFeatureActions& featureActions, QJsonObject& jsonObject, QStringList& featureActionsKeys); bool validateAudioInputDevice(SWGSDRangel::SWGAudioInputDevice& audioInputDevice, QJsonObject& jsonObject, QStringList& audioInputDeviceKeys); bool validateAudioOutputDevice(SWGSDRangel::SWGAudioOutputDevice& audioOutputDevice, QJsonObject& jsonObject, QStringList& audioOutputDeviceKeys); bool validateAMBEDevices(SWGSDRangel::SWGAMBEDevices& ambeDevices, QJsonObject& jsonObject); @@ -199,6 +209,9 @@ private: void resetChannelActions(SWGSDRangel::SWGChannelActions& channelActions); void resetAudioInputDevice(SWGSDRangel::SWGAudioInputDevice& audioInputDevice); void resetAudioOutputDevice(SWGSDRangel::SWGAudioOutputDevice& audioOutputDevice); + void resetFeatureSettings(SWGSDRangel::SWGFeatureSettings& deviceSettings); + void resetFeatureReport(SWGSDRangel::SWGFeatureReport& featureReport); + void resetFeatureActions(SWGSDRangel::SWGFeatureActions& featureActions); void processChannelAnalyzerSettings( SWGSDRangel::SWGChannelSettings *channelSettings,