From 518e480e99c74a09b60d136570bd0fae5d941435 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 12 Jan 2020 01:16:04 +0100 Subject: [PATCH] LimeRFE USB support: REST API: interface and mapper --- sdrbase/resources/webapi.qrc | 1 + .../webapi/doc/swagger/include/LimeRFE.yaml | 48 ++++ sdrbase/webapi/webapiadapterinterface.cpp | 3 + sdrbase/webapi/webapiadapterinterface.h | 67 +++++ sdrbase/webapi/webapirequestmapper.cpp | 266 +++++++++++++++++- sdrbase/webapi/webapirequestmapper.h | 4 + 6 files changed, 380 insertions(+), 9 deletions(-) create mode 100644 sdrbase/resources/webapi/doc/swagger/include/LimeRFE.yaml diff --git a/sdrbase/resources/webapi.qrc b/sdrbase/resources/webapi.qrc index a2f436913..d34873646 100644 --- a/sdrbase/resources/webapi.qrc +++ b/sdrbase/resources/webapi.qrc @@ -39,6 +39,7 @@ webapi/doc/swagger/include/Preferences.yaml webapi/doc/swagger/include/Preset.yaml webapi/doc/swagger/include/RtlSdr.yaml + webapi/doc/swagger/include/LimeRFE.yaml webapi/doc/swagger/include/LocalSink.yaml webapi/doc/swagger/include/LocalSource.yaml webapi/doc/swagger/include/RemoteSink.yaml diff --git a/sdrbase/resources/webapi/doc/swagger/include/LimeRFE.yaml b/sdrbase/resources/webapi/doc/swagger/include/LimeRFE.yaml new file mode 100644 index 000000000..e2ff585b1 --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/LimeRFE.yaml @@ -0,0 +1,48 @@ +LimeRFESettings: + description: LimeRFE + properties: + devicePath: + description: Path to the device serial interface (ex /dev/ttyUSB2) + type: string + rxChannels: + description: Rx channels group (see LimeRFEController.ChannelGroups enumeration) + type: integer + rxWidebandChannel: + descrition: Rx wideband channel selection (see LimeRFEController.WidebandChannel enumeration) + type: integer + rxHAMChannel: + description: Rx HAM channel selection (see LimeRFEController.HAMChannel enumeration) + type: integer + rxCellularChannel: + description: Rx cellular channel selection (see LimeRFEController.HAMChannel enumeration) + type: integer + rxPort: + description: Rx port selected (see LimeRFEController.RxPort enumeration) + type: integer + attenuationFactor: + description: Rx attenuation factor. Attenuation is 2 times this factor in dB (0..7 => 0..14dB) + type: integer + amfmNotch: + desciption: Rx AM/FM notch filter (boolean) + type: integer + txChannels: + description: Tx channels group (see LimeRFEController.ChannelGroups enumeration) + type: integer + txWidebandChannel: + descrition: Tx wideband channel selection (see LimeRFEController.WidebandChannel enumeration) + type: integer + txHAMChannel: + description: Tx HAM channel selection (see LimeRFEController.HAMChannel enumeration) + type: integer + txCellularChannel: + description: Tx cellular channel selection (see LimeRFEController.HAMChannel enumeration) + type: integer + txPort: + description: Tx port selected (see LimeRFEController.TxPort enumeration) + type: integer + rxOn: + description: Boolean 1 if Rx is active else 0 + type: integer + txOn: + description: Boolean 1 if Tx is active else 0 + type: integer \ No newline at end of file diff --git a/sdrbase/webapi/webapiadapterinterface.cpp b/sdrbase/webapi/webapiadapterinterface.cpp index f7e7e3ba2..89b1aadd1 100644 --- a/sdrbase/webapi/webapiadapterinterface.cpp +++ b/sdrbase/webapi/webapiadapterinterface.cpp @@ -32,6 +32,9 @@ QString WebAPIAdapterInterface::instanceAudioOutputCleanupURL = "/sdrangel/audio QString WebAPIAdapterInterface::instanceLocationURL = "/sdrangel/location"; QString WebAPIAdapterInterface::instanceAMBESerialURL = "/sdrangel/ambe/serial"; QString WebAPIAdapterInterface::instanceAMBEDevicesURL = "/sdrangel/ambe/devices"; +QString WebAPIAdapterInterface::instanceLimeRFESerialURL = "/sdrangel/limerfe/serial"; +QString WebAPIAdapterInterface::instanceLimeRFEConfigURL = "/sdrangel/limerfe/config"; +QString WebAPIAdapterInterface::instanceLimeRFERunURL = "/sdrangel/limerfe/run"; QString WebAPIAdapterInterface::instancePresetsURL = "/sdrangel/presets"; QString WebAPIAdapterInterface::instancePresetURL = "/sdrangel/preset"; QString WebAPIAdapterInterface::instancePresetFileURL = "/sdrangel/preset/file"; diff --git a/sdrbase/webapi/webapiadapterinterface.h b/sdrbase/webapi/webapiadapterinterface.h index 03e06f15a..ca5400c10 100644 --- a/sdrbase/webapi/webapiadapterinterface.h +++ b/sdrbase/webapi/webapiadapterinterface.h @@ -42,6 +42,8 @@ namespace SWGSDRangel class SWGLocationInformation; class SWGDVSerialDevices; class SWGAMBEDevices; + class SWGLimeRFEDevices; + class SWGLimeRFESettings; class SWGPresets; class SWGPresetTransfer; class SWGPresetIdentifier; @@ -423,6 +425,68 @@ public: return 501; } + /** + * Handler of /sdrangel/limerfe/serial (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels + * returns the Http status code (default 501: not implemented) + */ + virtual int instanceLimeRFESerialGet( + SWGSDRangel::SWGLimeRFEDevices& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/limerfe/config (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels + * returns the Http status code (default 501: not implemented) + */ + virtual int instanceLimeRFEConfigGet( + const QString& serial, + SWGSDRangel::SWGLimeRFESettings& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) serial; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/limerfe/config (PUT) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels + * returns the Http status code (default 501: not implemented) + */ + virtual int instanceLimeRFEConfigPut( + SWGSDRangel::SWGLimeRFESettings& query, + SWGSDRangel::SWGLimeRFESettings& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) query; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + + /** + * Handler of /sdrangel/limerfe/run (PUT) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels + * returns the Http status code (default 501: not implemented) + */ + virtual int instanceLimeRFERunPut( + SWGSDRangel::SWGLimeRFESettings& query, + SWGSDRangel::SWGSuccessResponse& response, + SWGSDRangel::SWGErrorResponse& error) + { + (void) query; + (void) response; + error.init(); + *error.getMessage() = QString("Function not implemented"); + return 501; + } + /** * Handler of /sdrangel/presets (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels * returns the Http status code (default 501: not implemented) @@ -904,6 +968,9 @@ public: static QString instanceLocationURL; static QString instanceAMBESerialURL; static QString instanceAMBEDevicesURL; + static QString instanceLimeRFESerialURL; + static QString instanceLimeRFEConfigURL; + static QString instanceLimeRFERunURL; static QString instancePresetsURL; static QString instancePresetURL; static QString instancePresetFileURL; diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 157942a9a..d7ddfd831 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -33,6 +33,8 @@ #include "SWGLocationInformation.h" #include "SWGDVSerialDevices.h" #include "SWGAMBEDevices.h" +#include "SWGLimeRFEDevices.h" +#include "SWGLimeRFESettings.h" #include "SWGPresets.h" #include "SWGPresetTransfer.h" #include "SWGPresetIdentifier.h" @@ -256,6 +258,12 @@ void WebAPIRequestMapper::service(qtwebapp::HttpRequest& request, qtwebapp::Http instanceAMBESerialService(request, response); } else if (path == WebAPIAdapterInterface::instanceAMBEDevicesURL) { instanceAMBEDevicesService(request, response); + } else if (path == WebAPIAdapterInterface::instanceLimeRFESerialURL) { + instanceLimeRFESerialService(request, response); + } else if (path == WebAPIAdapterInterface::instanceLimeRFEConfigURL) { + instanceLimeRFEConfigService(request, response); + } else if (path == WebAPIAdapterInterface::instanceLimeRFERunURL) { + instanceLimeRFERunService(request, response); } else if (path == WebAPIAdapterInterface::instancePresetsURL) { instancePresetsService(request, response); } else if (path == WebAPIAdapterInterface::instancePresetURL) { @@ -952,6 +960,174 @@ void WebAPIRequestMapper::instanceAMBEDevicesService(qtwebapp::HttpRequest& requ } } +void WebAPIRequestMapper::instanceLimeRFESerialService(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") + { + SWGSDRangel::SWGLimeRFEDevices normalResponse; + + int status = m_adapter->instanceLimeRFESerialGet(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()); + } +} + +void WebAPIRequestMapper::instanceLimeRFEConfigService(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") + { + QByteArray serialStr = request.getParameter("serial"); + SWGSDRangel::SWGLimeRFESettings normalResponse; + + int status = m_adapter->instanceLimeRFEConfigGet(serialStr, 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") + { + SWGSDRangel::SWGLimeRFESettings query; + SWGSDRangel::SWGLimeRFESettings normalResponse; + QString jsonStr = request.getBody(); + QJsonObject jsonObject; + + if (parseJsonBody(jsonStr, jsonObject, response)) + { + QStringList limeRFESettingsKeys; + + if (validateLimeRFEConfig(query, jsonObject, limeRFESettingsKeys)) + { + if (limeRFESettingsKeys.contains("devicePath")) + { + int status = m_adapter->instanceLimeRFEConfigPut(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,"LimeRFE device path expected in JSON body"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid 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(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()); + } +} + +void WebAPIRequestMapper::instanceLimeRFERunService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response) +{ + SWGSDRangel::SWGErrorResponse errorResponse; + response.setHeader("Content-Type", "application/json"); + response.setHeader("Access-Control-Allow-Origin", "*"); + + if (request.getMethod() == "PUT") + { + SWGSDRangel::SWGLimeRFESettings query; + QString jsonStr = request.getBody(); + QJsonObject jsonObject; + + if (parseJsonBody(jsonStr, jsonObject, response)) + { + QStringList limeRFESettingsKeys; + + if (validateLimeRFEConfig(query, jsonObject, limeRFESettingsKeys)) + { + if (limeRFESettingsKeys.contains("devicePath")) + { + SWGSDRangel::SWGSuccessResponse normalResponse; + int status = m_adapter->instanceLimeRFERunPut(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,"LimeRFE device path expected in JSON body"); + errorResponse.init(); + *errorResponse.getMessage() = "Invalid JSON format"; + 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(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()); + } +} + void WebAPIRequestMapper::instancePresetsService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response) { SWGSDRangel::SWGErrorResponse errorResponse; @@ -2302,6 +2478,87 @@ bool WebAPIRequestMapper::validateAMBEDevices(SWGSDRangel::SWGAMBEDevices& ambeD return false; } +bool WebAPIRequestMapper::validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings& limeRFESettings, QJsonObject& jsonObject, QStringList& limeRFESettingsKeys) +{ + if (jsonObject.contains("devicePath")) + { + limeRFESettings.setDevicePath(new QString(jsonObject["devicePath"].toString())); + limeRFESettingsKeys.append("devicePath"); + } + if (jsonObject.contains("rxChannels")) + { + limeRFESettings.setRxChannels(jsonObject["rxChannels"].toInt()); + limeRFESettingsKeys.append("rxChannels"); + } + if (jsonObject.contains("rxWidebandChannel")) + { + limeRFESettings.setRxWidebandChannel(jsonObject["rxWidebandChannel"].toInt()); + limeRFESettingsKeys.append("rxWidebandChannel"); + } + if (jsonObject.contains("rxHAMChannel")) + { + limeRFESettings.setRxHamChannel(jsonObject["rxHAMChannel"].toInt()); + limeRFESettingsKeys.append("rxHAMChannel"); + } + if (jsonObject.contains("rxCellularChannel")) + { + limeRFESettings.setRxCellularChannel(jsonObject["rxCellularChannel"].toInt()); + limeRFESettingsKeys.append("rxCellularChannel"); + } + if (jsonObject.contains("rxPort")) + { + limeRFESettings.setRxPort(jsonObject["rxPort"].toInt()); + limeRFESettingsKeys.append("rxPort"); + } + if (jsonObject.contains("attenuationFactor")) + { + limeRFESettings.setAttenuationFactor(jsonObject["attenuationFactor"].toInt()); + limeRFESettingsKeys.append("attenuationFactor"); + } + if (jsonObject.contains("amfmNotch")) + { + limeRFESettings.setAmfmNotch(jsonObject["amfmNotch"].toInt()); + limeRFESettingsKeys.append("amfmNotch"); + } + if (jsonObject.contains("txChannels")) + { + limeRFESettings.setTxChannels(jsonObject["txChannels"].toInt()); + limeRFESettingsKeys.append("txChannels"); + } + if (jsonObject.contains("txWidebandChannel")) + { + limeRFESettings.setTxWidebandChannel(jsonObject["txWidebandChannel"].toInt()); + limeRFESettingsKeys.append("txWidebandChannel"); + } + if (jsonObject.contains("txHAMChannel")) + { + limeRFESettings.setTxHamChannel(jsonObject["txHAMChannel"].toInt()); + limeRFESettingsKeys.append("txHAMChannel"); + } + if (jsonObject.contains("txCellularChannel")) + { + limeRFESettings.setTxCellularChannel(jsonObject["txCellularChannel"].toInt()); + limeRFESettingsKeys.append("txCellularChannel"); + } + if (jsonObject.contains("txPort")) + { + limeRFESettings.setTxPort(jsonObject["txPort"].toInt()); + limeRFESettingsKeys.append("txPort"); + } + if (jsonObject.contains("rxOn")) + { + limeRFESettings.setRxOn(jsonObject["rxOn"].toInt()); + limeRFESettingsKeys.append("rxOn"); + } + if (jsonObject.contains("txOn")) + { + limeRFESettings.setTxOn(jsonObject["txOn"].toInt()); + limeRFESettingsKeys.append("txOn"); + } + + return true; +} + bool WebAPIRequestMapper::validateConfig(SWGSDRangel::SWGInstanceConfigResponse& config, QJsonObject& jsonObject, WebAPIAdapterInterface::ConfigKeys& configKeys) { if (jsonObject.contains("preferences")) @@ -2813,15 +3070,6 @@ bool WebAPIRequestMapper::getDevice( deviceSettings->setTestSourceSettings(new SWGSDRangel::SWGTestSourceSettings()); deviceSettings->getTestSourceSettings()->fromJsonObject(settingsJsonObject); } - else if (deviceSettingsKey == "TestMISettings") - { - if (deviceSettingsKeys.contains("streams") && settingsJsonObject["streams"].isArray()) { - appendSettingsArrayKeys(settingsJsonObject, "streams", deviceSettingsKeys); - } - - deviceSettings->setTestMiSettings(new SWGSDRangel::SWGTestMISettings()); - deviceSettings->getTestMiSettings()->fromJsonObject(settingsJsonObject); - } else if (deviceSettingsKey == "XtrxInputSettings") { deviceSettings->setXtrxInputSettings(new SWGSDRangel::SWGXtrxInputSettings()); diff --git a/sdrbase/webapi/webapirequestmapper.h b/sdrbase/webapi/webapirequestmapper.h index 06bbc1b8e..2cacba90a 100644 --- a/sdrbase/webapi/webapirequestmapper.h +++ b/sdrbase/webapi/webapirequestmapper.h @@ -65,6 +65,9 @@ private: void instanceDVSerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void instanceAMBESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void instanceAMBEDevicesService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void instanceLimeRFESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void instanceLimeRFEConfigService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); + void instanceLimeRFERunService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void instancePresetsService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void instancePresetService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); void instancePresetFileService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response); @@ -93,6 +96,7 @@ private: 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); + bool validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings& limeRFESettings, QJsonObject& jsonObject, QStringList& limeRFESettingsKeys); bool validateConfig(SWGSDRangel::SWGInstanceConfigResponse& config, QJsonObject& jsonObject, WebAPIAdapterInterface::ConfigKeys& configKeys); bool appendPresetKeys(