/////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2020-2024 Jon Beniston, M7RCE // // Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation as version 3 of the License, or // // (at your option) any later version. // // // // This program is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License V3 for more details. // // // // You should have received a copy of the GNU General Public License // // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// #include #include "channelwebapiutils.h" #include "SWGDeviceState.h" #include "SWGErrorResponse.h" #include "SWGDeviceSettings.h" #include "SWGDeviceReport.h" #include "SWGChannelSettings.h" #include "SWGChannelActions.h" #include "SWGFileSinkActions.h" #include "SWGFeatureSettings.h" #include "SWGFeatureReport.h" #include "maincore.h" #include "device/deviceset.h" #include "device/deviceapi.h" #include "device/deviceenumerator.h" #include "channel/channelapi.h" #include "channel/channelutils.h" #include "dsp/devicesamplesource.h" #include "dsp/devicesamplesink.h" #include "dsp/devicesamplemimo.h" #include "webapi/webapiutils.h" #include "feature/featureset.h" #include "feature/feature.h" bool ChannelWebAPIUtils::getDeviceSettings(unsigned int deviceIndex, SWGSDRangel::SWGDeviceSettings &deviceSettingsResponse, DeviceSet *&deviceSet) { QString errorResponse; int httpRC; // Get current device settings std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { deviceSet = deviceSets[deviceIndex]; if (deviceSet->m_deviceSourceEngine) { deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceSettingsResponse.setDirection(0); DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); httpRC = source->webapiSettingsGet(deviceSettingsResponse, errorResponse); } else if (deviceSet->m_deviceSinkEngine) { deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceSettingsResponse.setDirection(1); DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink(); httpRC = sink->webapiSettingsGet(deviceSettingsResponse, errorResponse); } else if (deviceSet->m_deviceMIMOEngine) { deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceSettingsResponse.setDirection(2); DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO(); httpRC = mimo->webapiSettingsGet(deviceSettingsResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getDeviceSettings - not a sample source device " << deviceIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getDeviceSettings - no device " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getDeviceSettings: get device settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getDeviceReport(unsigned int deviceIndex, SWGSDRangel::SWGDeviceReport &deviceReport) { QString errorResponse; int httpRC; DeviceSet *deviceSet; // Get device report std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { deviceSet = deviceSets[deviceIndex]; if (deviceSet->m_deviceSourceEngine) { deviceReport.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceReport.setDirection(0); DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); httpRC = source->webapiReportGet(deviceReport, errorResponse); } else if (deviceSet->m_deviceSinkEngine) { deviceReport.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceReport.setDirection(1); DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink(); httpRC = sink->webapiReportGet(deviceReport, errorResponse); } else if (deviceSet->m_deviceMIMOEngine) { deviceReport.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId())); deviceReport.setDirection(2); DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO(); httpRC = mimo->webapiReportGet(deviceReport, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getDeviceReport: unknown device type " << deviceIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getDeviceReport: no device " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getDeviceReport: get device report error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getFeatureSettings(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureSettings &featureSettingsResponse, Feature *&feature) { QString errorResponse; int httpRC; FeatureSet *featureSet; // Get current feature settings std::vector featureSets = MainCore::instance()->getFeatureeSets(); if (featureSetIndex < featureSets.size()) { featureSet = featureSets[featureSetIndex]; if (featureIndex < (unsigned int)featureSet->getNumberOfFeatures()) { feature = featureSet->getFeatureAt(featureIndex); httpRC = feature->webapiSettingsGet(featureSettingsResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getFeatureSettings: no feature " << featureSetIndex << ":" << featureIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getFeatureSettings: no feature set " << featureSetIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getFeatureSettings: get feature settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getFeatureReport(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureReport &featureReport) { QString errorResponse; int httpRC; FeatureSet *featureSet; Feature *feature; // Get feature report std::vector featureSets = MainCore::instance()->getFeatureeSets(); if (featureSetIndex < featureSets.size()) { featureSet = featureSets[featureSetIndex]; if (featureIndex < (unsigned int)featureSet->getNumberOfFeatures()) { feature = featureSet->getFeatureAt(featureIndex); httpRC = feature->webapiReportGet(featureReport, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getFeatureReport: no feature " << featureSetIndex << ":" << featureIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getFeatureReport: no feature set " << featureSetIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getFeatureReport: get feature report error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getChannelSettings(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelSettings &channelSettingsResponse, ChannelAPI *&channel) { QString errorResponse; int httpRC; DeviceSet *deviceSet; // Get current channel settings std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { deviceSet = deviceSets[deviceIndex]; if (channelIndex < (unsigned int) deviceSet->getNumberOfChannels()) { channel = deviceSet->getChannelAt(channelIndex); httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getChannelSettings: no channel " << deviceIndex << ":" << channelIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getChannelSettings: no device " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getChannelSettings: get channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getChannelSettings(ChannelAPI *channel, SWGSDRangel::SWGChannelSettings &channelSettingsResponse) { QString errorResponse; int httpRC; httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getChannelSettings: get channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::getChannelReport(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelReport &channelReport) { QString errorResponse; int httpRC; DeviceSet *deviceSet; // Get channel report std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { deviceSet = deviceSets[deviceIndex]; if (channelIndex < (unsigned int) deviceSet->getNumberOfChannels()) { ChannelAPI *channel = deviceSet->getChannelAt(channelIndex); httpRC = channel->webapiReportGet(channelReport, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::getChannelReport: no channel " << deviceIndex << ":" << channelIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::getChannelReport: no device set " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getChannelReport: get channel report error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } QString ChannelWebAPIUtils::getDeviceHardwareId(unsigned int deviceIndex) { DeviceAPI *deviceAPI = MainCore::instance()->getDevice(deviceIndex); if (deviceAPI) { return deviceAPI->getHardwareId(); } else { return QString(); } } // Get device center frequency bool ChannelWebAPIUtils::getCenterFrequency(unsigned int deviceIndex, double &frequencyInHz) { SWGSDRangel::SWGDeviceSettings deviceSettingsResponse; DeviceSet *deviceSet; if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet)) { QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz); delete jsonObj; return result; } else { return false; } } // Set device center frequency // Doesn't support MIMO devices. We'd need stream index parameter bool ChannelWebAPIUtils::setCenterFrequency(unsigned int deviceIndex, double frequencyInHz) { SWGSDRangel::SWGDeviceSettings deviceSettingsResponse; int httpRC = 404; DeviceSet *deviceSet; if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet)) { // Patch centerFrequency QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject(); double freq; if (WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", freq)) { WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz); QStringList deviceSettingsKeys; deviceSettingsKeys.append("centerFrequency"); deviceSettingsResponse.init(); deviceSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); if (source) { httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); } DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink(); if (sink) { httpRC = sink->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); } if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::setCenterFrequency: set device frequency %f OK", frequencyInHz); return true; } else { qWarning("ChannelWebAPIUtils::setCenterFrequency: set device frequency error %d: %s", httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { qWarning("ChannelWebAPIUtils::setCenterFrequency: no centerFrequency key in device settings"); return false; } } else { return false; } } // Get local oscillator frequency correction bool ChannelWebAPIUtils::getLOPpmCorrection(unsigned int deviceIndex, int &ppmTenths) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "RTLSDR") { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "loPpmCorrection", ppmTenths); } else { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "LOppmTenths", ppmTenths); } } // Set local oscillator frequency correction bool ChannelWebAPIUtils::setLOPpmCorrection(unsigned int deviceIndex, int ppmTenths) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "RTLSDR") { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "loPpmCorrection", ppmTenths); // RTLSDR } else { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "LOppmTenths", ppmTenths); // Airspy, AirspyHF. BladeRF2, FCDPro, HackRF, Metis, Perseus, Pluto, SDRPlay, SDRplayV3, SaopySDR } } // Get device sample rate bool ChannelWebAPIUtils::getDevSampleRate(unsigned int deviceIndex, int &devSampleRate) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "AirspyHF") { QList rates; int idx; if (ChannelWebAPIUtils::getDeviceReportList(deviceIndex, "sampleRates", "rate", rates) && ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "devSampleRateIndex", idx)) { if (idx < rates.size()) { devSampleRate = rates[idx]; return true; } } return false; } else { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "devSampleRate", devSampleRate); } } // Set device sample rate bool ChannelWebAPIUtils::setDevSampleRate(unsigned int deviceIndex, int devSampleRate) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "AirspyHF") { QList rates; ChannelWebAPIUtils::getDeviceReportList(deviceIndex, "sampleRates", "rate", rates); // Find first rate that is big enough. Higher rates are in list first int idx = 0; for (int i = rates.size() - 1; i >= 0; i--) { if (devSampleRate <= rates[i]) { idx = i; break; } } return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "devSampleRateIndex", idx); } else { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "devSampleRate", devSampleRate); } } bool ChannelWebAPIUtils::getGain(unsigned int deviceIndex, int stage, int &gain) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); bool error = true; if ((devId == "Airspy")) { QStringList airspyStages = {"lnaGain", "mixerGain", "vgaGain"}; if (stage < airspyStages.size()) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, airspyStages[stage], gain); gain *= 10; } } else if ((devId == "AirspyHF")) { if (stage == 0) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "attenuatorSteps", gain); gain *= 10 * 6; } } else if ((devId == "BladeRF1")) { QStringList bladeRF1Stages = {"lnaGain", "vga1", "vga2"}; if (stage < bladeRF1Stages.size()) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, bladeRF1Stages[stage], gain); gain *= 10; } } else if ((devId == "HackRF")) { QStringList hackRFStages = {"lnaGain", "vgaGain"}; if (stage < hackRFStages.size()) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, hackRFStages[stage], gain); gain *= 10; } } else if ((devId == "FCDProPlus") || (devId == "KiwiSDR") || (devId == "LimeSDR") || (devId == "PlutoSDR") || (devId == "USRP") || (devId == "XTRX")) { if (stage == 0) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "gain", gain); gain *= 10; } } else if ((devId == "SDRplayV3")) { QStringList sdrplayStages = {"lnaGain", "ifGain"}; if (stage < sdrplayStages.size()) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, sdrplayStages[stage], gain); gain *= 10; } } else if ((devId == "RTLSDR")) { if (stage == 0) { error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "gain", gain); } } return error; } // Set gain for different stages in RF device // Gain is generally in 10ths of a dB // Stages should correspond with order in RemoteTCPInputGUI bool ChannelWebAPIUtils::setGain(unsigned int deviceIndex, int stage, int gain) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "Airspy") { QStringList airspyStages = {"lnaGain", "mixerGain", "vgaGain"}; if (stage < airspyStages.size()) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, airspyStages[stage], gain / 10); } } else if (devId == "AirspyHF") { if (stage == 0) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "attenuatorSteps", gain / 10 / 6); } } else if (devId == "BladeRF1") { QStringList bladeRF1Stages = {"lnaGain", "vga1", "vga2"}; if (stage < bladeRF1Stages.size()) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, bladeRF1Stages[stage], gain / 10); } } else if (devId == "HackRF") { QStringList hackRFStages = {"lnaGain", "vgaGain"}; if (stage < hackRFStages.size()) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, hackRFStages[stage], gain / 10); } } else if ((devId == "FCDProPlus") || (devId == "KiwiSDR") || (devId == "LimeSDR") || (devId == "PlutoSDR") || (devId == "USRP") || (devId == "XTRX")) { if (stage == 0) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "gain", gain / 10); } } else if (devId == "SDRplayV3") { QStringList sdrplayStages = {"lnaGain", "ifGain"}; if (stage < sdrplayStages.size()) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, sdrplayStages[stage], gain / 10); } } else if ((devId == "RTLSDR")) { if (stage == 0) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "gain", gain); } } return false; } bool ChannelWebAPIUtils::getAGC(unsigned int deviceIndex, int &enabled) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "Airspy")) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "lnaAGC", enabled); // What about mixerAGC? } else if ((devId == "AirspyHF") || (devId == "KiwiSDR")) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "useAGC", enabled); } else if ((devId == "LimeSDR") || (devId == "PlutoSDR") || (devId == "USRP") || (devId == "XTRX")) { bool error = ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "gainMode", enabled); enabled = !enabled; return error; } else if (devId == "RTLSDR") { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "agc", enabled); } else if (devId == "SDRplayV3") { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "ifAGC", enabled); } return false; } bool ChannelWebAPIUtils::setAGC(unsigned int deviceIndex, bool enabled) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "Airspy")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "lnaAGC", enabled) && ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "mixerAGC", enabled); } else if ((devId == "AirspyHF") || (devId == "KiwiSDR")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "useAGC", enabled); } else if ((devId == "LimeSDR") || (devId == "PlutoSDR") || (devId == "USRP") || (devId == "XTRX")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "gainMode", !enabled); } else if (devId == "RTLSDR") { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "agc", enabled); } else if (devId == "SDRplayV3") { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "ifAGC", enabled); } return false; } // Get RF bandwidth bool ChannelWebAPIUtils::getRFBandwidth(unsigned int deviceIndex, int &bw) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "RTLSDR") { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "rfBandwidth", bw); } else if ((devId == "BladeRF1") || (devId == "HackRF")) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "bandwidth", bw); } else if (devId == "SDRplayV3") { QList bws; int idx; if (ChannelWebAPIUtils::getDeviceReportList(deviceIndex, "bandwidths", "bandwidth", bws) && ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "bandwidthIndex", idx)) { if (idx < bws.size()) { bw = bws[idx]; return true; } } return false; } else { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "lpfBW", bw); } } // Set RF bandwidth bool ChannelWebAPIUtils::setRFBandwidth(unsigned int deviceIndex, int bw) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if (devId == "RTLSDR") { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "rfBandwidth", bw); // RTLSDR } else if ((devId == "BladeRF1") || (devId == "HackRF")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "bandwidth", bw); // BladeRF1, HackRF } else if (devId == "SDRplayV3") { QList bws; ChannelWebAPIUtils::getDeviceReportList(deviceIndex, "bandwidths", "bandwidth", bws); // Find first b/w that is big enough int idx = 0; for (int i = 0; i < bws.size(); i++) { if (bw <= bws[i]) { break; } idx++; } return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "bandwidthIndex", idx); } else { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "lpfBW", bw); // LimeSDR, PlutoSDR, USRP } // TODO: SDRPlay and SDRPlayV3 use bandwidthIndex } // Get software decimation bool ChannelWebAPIUtils::getSoftDecim(unsigned int deviceIndex, int &log2Decim) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "LimeSDR") || (devId == "USRP")) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "log2SoftDecim", log2Decim); } else { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "log2Decim", log2Decim); } } // Set software decimation bool ChannelWebAPIUtils::setSoftDecim(unsigned int deviceIndex, int log2Decim) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "LimeSDR") || (devId == "USRP")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "log2SoftDecim", log2Decim); // LimeSDR, USRP } else { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "log2Decim", log2Decim); } } // Get whether bias tee is enabled bool ChannelWebAPIUtils::getBiasTee(unsigned int deviceIndex, int &enabled) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "RTLSDR") || (devId == "BladeRF") || (devId == "SDRplayV3")) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "biasTee", enabled); } else { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "biasT", enabled); } } // Set whether bias tee, if available, should be enabled bool ChannelWebAPIUtils::setBiasTee(unsigned int deviceIndex, bool enabled) { QString devId = ChannelWebAPIUtils::getDeviceHardwareId(deviceIndex); if ((devId == "RTLSDR") || (devId == "BladeRF") || (devId == "SDRplayV3")) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "biasTee", enabled); // RTLSDR, BladeRF, SDRplayV3 } else { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "biasT", enabled); // Airspy, FCDProPlus, HackRF, } } // Get whether DC offset removal is enabled bool ChannelWebAPIUtils::getDCOffsetRemoval(unsigned int deviceIndex, int &enabled) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "dcBlock", enabled); } // Set whether DC offset removal should be enabled bool ChannelWebAPIUtils::setDCOffsetRemoval(unsigned int deviceIndex, bool enabled) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "dcBlock", enabled); } // Get whether IQ correction is enabled bool ChannelWebAPIUtils::getIQCorrection(unsigned int deviceIndex, int &enabled) { return ChannelWebAPIUtils::getDeviceSetting(deviceIndex, "iqCorrection", enabled); } // Set whether IQ correction should be enabled bool ChannelWebAPIUtils::setIQCorrection(unsigned int deviceIndex, bool enabled) { return ChannelWebAPIUtils::patchDeviceSetting(deviceIndex, "iqCorrection", enabled); } // Start acquisition bool ChannelWebAPIUtils::run(unsigned int deviceIndex, int subsystemIndex) { SWGSDRangel::SWGDeviceState runResponse; QString errorResponse; int httpRC; DeviceSet *deviceSet; std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { runResponse.setState(new QString()); deviceSet = deviceSets[deviceIndex]; if (deviceSet->m_deviceSourceEngine) { DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); httpRC = source->webapiRun(1, runResponse, errorResponse); } else if (deviceSet->m_deviceSinkEngine) { DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink(); httpRC = sink->webapiRun(1, runResponse, errorResponse); } else if (deviceSet->m_deviceMIMOEngine) { DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO(); httpRC = mimo->webapiRun(1, subsystemIndex, runResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::run - unknown device " << deviceIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::run - no device " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::run: run error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } // Stop acquisition bool ChannelWebAPIUtils::stop(unsigned int deviceIndex, int subsystemIndex) { SWGSDRangel::SWGDeviceState runResponse; QString errorResponse; int httpRC; DeviceSet *deviceSet; std::vector deviceSets = MainCore::instance()->getDeviceSets(); if (deviceIndex < deviceSets.size()) { runResponse.setState(new QString()); deviceSet = deviceSets[deviceIndex]; if (deviceSet->m_deviceSourceEngine) { DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); httpRC = source->webapiRun(0, runResponse, errorResponse); } else if (deviceSet->m_deviceSinkEngine) { DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink(); httpRC = sink->webapiRun(0, runResponse, errorResponse); } else if (deviceSet->m_deviceMIMOEngine) { DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO(); httpRC = mimo->webapiRun(0, subsystemIndex, runResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::stop - unknown device " << deviceIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::stop - no device " << deviceIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::stop: run error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } // Get input frequency offset for a channel bool ChannelWebAPIUtils::getFrequencyOffset(unsigned int deviceIndex, int channelIndex, int& offset) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; QString errorResponse; int httpRC; QJsonObject *jsonObj; double offsetD; ChannelAPI *channel = MainCore::instance()->getChannel(deviceIndex, channelIndex); if (channel != nullptr) { httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::getFrequencyOffset: get channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } jsonObj = channelSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, "inputFrequencyOffset", offsetD); delete jsonObj; if (result) { offset = (int)offsetD; return true; } } return false; } // Set input frequency offset for a channel bool ChannelWebAPIUtils::setFrequencyOffset(unsigned int deviceIndex, int channelIndex, int offset) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; QString errorResponse; int httpRC; QJsonObject *jsonObj; ChannelAPI *channel = MainCore::instance()->getChannel(deviceIndex, channelIndex); if (channel != nullptr) { httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::setFrequencyOffset: get channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } jsonObj = channelSettingsResponse.asJsonObject(); if (WebAPIUtils::setSubObjectDouble(*jsonObj, "inputFrequencyOffset", (double)offset)) { QStringList keys; keys.append("inputFrequencyOffset"); channelSettingsResponse.init(); channelSettingsResponse.fromJsonObject(*jsonObj); delete jsonObj; httpRC = channel->webapiSettingsPutPatch(false, keys, channelSettingsResponse, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::setFrequencyOffset: patch channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } delete jsonObj; } return false; } bool ChannelWebAPIUtils::setAudioMute(unsigned int deviceIndex, int channelIndex, bool mute) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; QString errorResponse; int httpRC; QJsonObject* jsonObj; ChannelAPI* channel = MainCore::instance()->getChannel(deviceIndex, channelIndex); if (channel != nullptr) { httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); if (httpRC / 100 != 2) { qWarning("ChannelWebAPIUtils::setAudioMute: get channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } jsonObj = channelSettingsResponse.asJsonObject(); if (WebAPIUtils::setSubObjectInt(*jsonObj, "audioMute", (int)mute)) { QStringList keys; keys.append("audioMute"); channelSettingsResponse.init(); channelSettingsResponse.fromJsonObject(*jsonObj); delete jsonObj; httpRC = channel->webapiSettingsPutPatch(false, keys, channelSettingsResponse, errorResponse); if (httpRC / 100 != 2) { qWarning("ChannelWebAPIUtils::setAudioMute: patch channel settings error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } delete jsonObj; } return false; } // Start or stop all file sinks in a given device set bool ChannelWebAPIUtils::startStopFileSinks(unsigned int deviceIndex, bool start) { MainCore *mainCore = MainCore::instance(); ChannelAPI *channel; int channelIndex = 0; while(nullptr != (channel = mainCore->getChannel(deviceIndex, channelIndex))) { if (ChannelUtils::compareChannelURIs(channel->getURI(), "sdrangel.channel.filesink")) { QStringList channelActionKeys = {"record"}; SWGSDRangel::SWGChannelActions channelActions; SWGSDRangel::SWGFileSinkActions *fileSinkAction = new SWGSDRangel::SWGFileSinkActions(); QString errorResponse; int httpRC; fileSinkAction->setRecord(start); channelActions.setFileSinkActions(fileSinkAction); httpRC = channel->webapiActionsPost(channelActionKeys, channelActions, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::startStopFileSinks: webapiActionsPost error %d: %s", httpRC, qPrintable(errorResponse)); return false; } } channelIndex++; } return true; } // Send AOS actions to all channels that support it // See also: FeatureWebAPIUtils::satelliteAOS bool ChannelWebAPIUtils::satelliteAOS(const QString name, bool northToSouthPass, const QString &tle, QDateTime dateTime) { MainCore *mainCore = MainCore::instance(); std::vector deviceSets = mainCore->getDeviceSets(); for (unsigned int deviceIndex = 0; deviceIndex < deviceSets.size(); deviceIndex++) { ChannelAPI *channel; int channelIndex = 0; while(nullptr != (channel = mainCore->getChannel(deviceIndex, channelIndex))) { if (ChannelUtils::compareChannelURIs(channel->getURI(), "sdrangel.channel.aptdemod")) { QStringList channelActionKeys = {"aos"}; SWGSDRangel::SWGChannelActions channelActions; SWGSDRangel::SWGAPTDemodActions *aptDemodAction = new SWGSDRangel::SWGAPTDemodActions(); SWGSDRangel::SWGAPTDemodActions_aos *aosAction = new SWGSDRangel::SWGAPTDemodActions_aos(); QString errorResponse; int httpRC; aosAction->setSatelliteName(new QString(name)); aosAction->setNorthToSouthPass(northToSouthPass); aosAction->setTle(new QString(tle)); aosAction->setDateTime(new QString(dateTime.toString(Qt::ISODateWithMs))); aptDemodAction->setAos(aosAction); channelActions.setAptDemodActions(aptDemodAction); httpRC = channel->webapiActionsPost(channelActionKeys, channelActions, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::satelliteAOS: webapiActionsPost error %d: %s", httpRC, qPrintable(errorResponse)); return false; } } channelIndex++; } } return true; } // Send LOS actions to all channels that support it bool ChannelWebAPIUtils::satelliteLOS(const QString name) { MainCore *mainCore = MainCore::instance(); std::vector deviceSets = mainCore->getDeviceSets(); for (unsigned int deviceIndex = 0; deviceIndex < deviceSets.size(); deviceIndex++) { ChannelAPI *channel; int channelIndex = 0; while(nullptr != (channel = mainCore->getChannel(deviceIndex, channelIndex))) { if (ChannelUtils::compareChannelURIs(channel->getURI(), "sdrangel.channel.aptdemod")) { QStringList channelActionKeys = {"los"}; SWGSDRangel::SWGChannelActions channelActions; SWGSDRangel::SWGAPTDemodActions *aptDemodAction = new SWGSDRangel::SWGAPTDemodActions(); SWGSDRangel::SWGAPTDemodActions_los *losAction = new SWGSDRangel::SWGAPTDemodActions_los(); QString errorResponse; int httpRC; losAction->setSatelliteName(new QString(name)); aptDemodAction->setLos(losAction); channelActions.setAptDemodActions(aptDemodAction); httpRC = channel->webapiActionsPost(channelActionKeys, channelActions, errorResponse); if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::satelliteLOS: webapiActionsPost error %d: %s", httpRC, qPrintable(errorResponse)); return false; } } channelIndex++; } } return true; } bool ChannelWebAPIUtils::getDeviceSetting(unsigned int deviceIndex, const QString &setting, int &value) { SWGSDRangel::SWGDeviceSettings deviceSettingsResponse; DeviceSet *deviceSet; if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet)) { QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectInt(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getDeviceReportValue(unsigned int deviceIndex, const QString &key, QString &value) { SWGSDRangel::SWGDeviceReport deviceReport; if (getDeviceReport(deviceIndex, deviceReport)) { // Get value of requested key QJsonObject *jsonObj = deviceReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectString(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getDeviceReportValue: no key %s in device report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getDeviceReportList(unsigned int deviceIndex, const QString &key, const QString &subKey, QList &values) { SWGSDRangel::SWGDeviceReport deviceReport; if (getDeviceReport(deviceIndex, deviceReport)) { // Get value of requested key QJsonObject *jsonObj = deviceReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectIntList(*jsonObj, key, subKey, values); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getDeviceReportList: no key %s in device report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getDevicePosition(unsigned int deviceIndex, float& latitude, float& longitude, float& altitude) { SWGSDRangel::SWGDeviceReport deviceReport; if (getDeviceReport(deviceIndex, deviceReport)) { QJsonObject *jsonObj = deviceReport.asJsonObject(); double latitudeDouble, longitudeDouble, altitudeDouble; bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, "latitude", latitudeDouble) && WebAPIUtils::getSubObjectDouble(*jsonObj, "longitude", longitudeDouble) && WebAPIUtils::getSubObjectDouble(*jsonObj, "altitude", altitudeDouble); delete jsonObj; if (result) { if (!std::isnan(latitudeDouble) && !std::isnan(longitudeDouble) && !std::isnan(altitudeDouble)) { latitude = (float) latitudeDouble; longitude = (float) longitudeDouble; altitude = (float) altitudeDouble; return true; } } } return false; } bool ChannelWebAPIUtils::runFeature(unsigned int featureSetIndex, unsigned int featureIndex) { SWGSDRangel::SWGDeviceState runResponse; QString errorResponse; int httpRC; FeatureSet *featureSet; Feature *feature; std::vector featureSets = MainCore::instance()->getFeatureeSets(); if (featureSetIndex < featureSets.size()) { runResponse.setState(new QString()); featureSet = featureSets[featureSetIndex]; if (featureIndex < (unsigned int)featureSet->getNumberOfFeatures()) { feature = featureSet->getFeatureAt(featureIndex); httpRC = feature->webapiRun(1, runResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::runFeature - no feature " << featureSetIndex << ':' << featureIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::runFeature - no feature set " << featureSetIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::runFeature: run error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::stopFeature(unsigned int featureSetIndex, unsigned int featureIndex) { SWGSDRangel::SWGDeviceState runResponse; QString errorResponse; int httpRC; FeatureSet *featureSet; Feature *feature; std::vector featureSets = MainCore::instance()->getFeatureeSets(); if (featureSetIndex < featureSets.size()) { runResponse.setState(new QString()); featureSet = featureSets[featureSetIndex]; if (featureIndex < (unsigned int)featureSet->getNumberOfFeatures()) { feature = featureSet->getFeatureAt(featureIndex); httpRC = feature->webapiRun(0, runResponse, errorResponse); } else { qDebug() << "ChannelWebAPIUtils::stopFeature - no feature " << featureSetIndex << ':' << featureIndex; return false; } } else { qDebug() << "ChannelWebAPIUtils::stopFeature - no feature set " << featureSetIndex; return false; } if (httpRC/100 != 2) { qWarning("ChannelWebAPIUtils::stopFeature: run error %d: %s", httpRC, qPrintable(errorResponse)); return false; } return true; } bool ChannelWebAPIUtils::patchDeviceSetting(unsigned int deviceIndex, const QString &setting, int value) { SWGSDRangel::SWGDeviceSettings deviceSettingsResponse; QString errorResponse; int httpRC; DeviceSet *deviceSet; if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet)) { // Patch setting QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject(); int oldValue; if (WebAPIUtils::getSubObjectInt(*jsonObj, setting, oldValue)) { WebAPIUtils::setSubObjectInt(*jsonObj, setting, value); QStringList deviceSettingsKeys; deviceSettingsKeys.append(setting); deviceSettingsResponse.init(); deviceSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource(); httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchDeviceSetting: set device setting %s OK", qPrintable(setting)); return true; } else { qWarning("ChannelWebAPIUtils::patchDeviceSetting: set device setting error %d: %s", httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { delete jsonObj; qWarning("ChannelWebAPIUtils::patchDeviceSetting: no key %s in device settings", qPrintable(setting)); return false; } } else { return false; } } // Set feature setting bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; int httpRC; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { // Patch settings QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); QString oldValue; if (WebAPIUtils::getSubObjectString(*jsonObj, setting, oldValue)) { WebAPIUtils::setSubObjectString(*jsonObj, setting, value); QStringList featureSettingsKeys; featureSettingsKeys.append(setting); featureSettingsResponse.init(); featureSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; httpRC = feature->webapiSettingsPutPatch(false, featureSettingsKeys, featureSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %s OK", qPrintable(setting), qPrintable(value)); return true; } else { qWarning("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %s error %d: %s", qPrintable(setting), qPrintable(value), httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { delete jsonObj; qWarning("ChannelWebAPIUtils::patchFeatureSetting: no key %s in feature settings", qPrintable(setting)); return false; } } else { return false; } } bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; QString errorResponse; int httpRC; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { // Patch settings QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); double oldValue; if (WebAPIUtils::getSubObjectDouble(*jsonObj, setting, oldValue)) { WebAPIUtils::setSubObjectDouble(*jsonObj, setting, value); QStringList featureSettingsKeys; featureSettingsKeys.append(setting); featureSettingsResponse.init(); featureSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; httpRC = feature->webapiSettingsPutPatch(false, featureSettingsKeys, featureSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %f OK", qPrintable(setting), value); return true; } else { qWarning("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %f error %d: %s", qPrintable(setting), value, httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { delete jsonObj; qWarning("ChannelWebAPIUtils::patchFeatureSetting: no key %s in feature settings", qPrintable(setting)); return false; } } else { return false; } } bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QJsonArray& value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; QString errorResponse; int httpRC; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { // Patch settings QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); // Set value bool found = false; for (QJsonObject::iterator it = jsonObj->begin(); it != jsonObj->end(); it++) { QJsonValue jsonValue = it.value(); if (jsonValue.isObject()) { QJsonObject subObject = jsonValue.toObject(); if (subObject.contains(setting)) { subObject[setting] = value; it.value() = subObject; found = true; break; } } } if (!found) { for (QJsonObject::iterator it = jsonObj->begin(); it != jsonObj->end(); it++) { QJsonValueRef jsonValue = it.value(); if (jsonValue.isObject()) { QJsonObject subObject = jsonValue.toObject(); subObject.insert(setting, value); jsonValue = subObject; } } } QStringList featureSettingsKeys; featureSettingsKeys.append(setting); featureSettingsResponse.init(); featureSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; httpRC = feature->webapiSettingsPutPatch(false, featureSettingsKeys, featureSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s OK", qPrintable(setting)); return true; } else { qWarning("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s error %d: %s", qPrintable(setting), httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { return false; } } bool ChannelWebAPIUtils::patchChannelSetting(ChannelAPI *channel, const QString &setting, const QVariant& value) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; QString errorResponse; int httpRC; if (getChannelSettings(channel, channelSettingsResponse)) { // Patch settings QJsonObject *jsonObj = channelSettingsResponse.asJsonObject(); if (WebAPIUtils::hasSubObject(*jsonObj, setting)) { WebAPIUtils::setSubObject(*jsonObj, setting, value); QStringList channelSettingsKeys; channelSettingsKeys.append(setting); channelSettingsResponse.init(); channelSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; httpRC = channel->webapiSettingsPutPatch(false, channelSettingsKeys, channelSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchChannelSetting: set feature setting %s to %s OK", qPrintable(setting), qPrintable(value.toString())); return true; } else { qWarning("ChannelWebAPIUtils::patchChannelSetting: set feature setting %s to %s error %d: %s", qPrintable(setting), qPrintable(value.toString()), httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { delete jsonObj; qWarning("ChannelWebAPIUtils::patchChannelSetting: no key %s in channel settings", qPrintable(setting)); return false; } } else { return false; } } bool ChannelWebAPIUtils::patchChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, const QString& value) { ChannelAPI *channel = MainCore::instance()->getChannel(deviceSetIndex, channelIndex); if (channel) { return patchChannelSetting(channel, setting, value); } else { return false; } } bool ChannelWebAPIUtils::patchChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, int value) { ChannelAPI *channel = MainCore::instance()->getChannel(deviceSetIndex, channelIndex); if (channel) { return patchChannelSetting(channel, setting, value); } else { return false; } } bool ChannelWebAPIUtils::patchChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, double value) { ChannelAPI *channel = MainCore::instance()->getChannel(deviceSetIndex, channelIndex); if (channel) { return patchChannelSetting(channel, setting, value); } else { return false; } } bool ChannelWebAPIUtils::patchChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, const QJsonArray& value) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; QString errorResponse; int httpRC; ChannelAPI *channel; if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel)) { // Patch setting QJsonObject *jsonObj = channelSettingsResponse.asJsonObject(); // Set value bool found = false; for (QJsonObject::iterator it = jsonObj->begin(); it != jsonObj->end(); it++) { QJsonValue jsonValue = it.value(); if (jsonValue.isObject()) { QJsonObject subObject = jsonValue.toObject(); if (subObject.contains(setting)) { subObject[setting] = value; it.value() = subObject; found = true; break; } } } if (!found) { for (QJsonObject::iterator it = jsonObj->begin(); it != jsonObj->end(); it++) { QJsonValueRef jsonValue = it.value(); if (jsonValue.isObject()) { QJsonObject subObject = jsonValue.toObject(); subObject.insert(setting, value); jsonValue = subObject; } } } QStringList channelSettingsKeys; channelSettingsKeys.append(setting); channelSettingsResponse.init(); channelSettingsResponse.fromJsonObject(*jsonObj); SWGSDRangel::SWGErrorResponse errorResponse2; delete jsonObj; httpRC = channel->webapiSettingsPutPatch(false, channelSettingsKeys, channelSettingsResponse, *errorResponse2.getMessage()); if (httpRC/100 == 2) { qDebug("ChannelWebAPIUtils::patchChannelSetting: set channel setting %s OK", qPrintable(setting)); return true; } else { qWarning("ChannelWebAPIUtils::patchChannelSetting: set channel setting error %d: %s", httpRC, qPrintable(*errorResponse2.getMessage())); return false; } } else { return false; } } bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, int &value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectInt(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double &value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, QString &value) { SWGSDRangel::SWGFeatureSettings featureSettingsResponse; Feature *feature; if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature)) { QJsonObject *jsonObj = featureSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectString(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, int &value) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; ChannelAPI *channel; if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel)) { QJsonObject *jsonObj = channelSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectInt(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, double &value) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; ChannelAPI *channel; if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel)) { QJsonObject *jsonObj = channelSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, QString &value) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; ChannelAPI *channel; if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel)) { QJsonObject *jsonObj = channelSettingsResponse.asJsonObject(); bool result = WebAPIUtils::getSubObjectString(*jsonObj, setting, value); delete jsonObj; return result; } else { return false; } } bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, int &value) { SWGSDRangel::SWGFeatureReport featureReport; if (getFeatureReport(featureSetIndex, featureIndex, featureReport)) { // Get value of requested key QJsonObject *jsonObj = featureReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectInt(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getFeatureReportValue: no key %s in feature report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, double &value) { SWGSDRangel::SWGFeatureReport featureReport; if (getFeatureReport(featureSetIndex, featureIndex, featureReport)) { // Get value of requested key QJsonObject *jsonObj = featureReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getFeatureReportValue: no key %s in feature report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, QString &value) { SWGSDRangel::SWGFeatureReport featureReport; if (getFeatureReport(featureSetIndex, featureIndex, featureReport)) { // Get value of requested key QJsonObject *jsonObj = featureReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectString(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getFeatureReportValue: no key %s in feature report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, int &value) { SWGSDRangel::SWGChannelReport channelReport; if (getChannelReport(deviceIndex, channelIndex, channelReport)) { // Get value of requested key QJsonObject *jsonObj = channelReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectInt(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, double &value) { SWGSDRangel::SWGChannelReport channelReport; if (getChannelReport(deviceIndex, channelIndex, channelReport)) { // Get value of requested key QJsonObject *jsonObj = channelReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectDouble(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, QString &value) { SWGSDRangel::SWGChannelReport channelReport; if (getChannelReport(deviceIndex, channelIndex, channelReport)) { // Get value of requested key QJsonObject *jsonObj = channelReport.asJsonObject(); bool result = WebAPIUtils::getSubObjectString(*jsonObj, key, value); delete jsonObj; if (result) { // Done return true; } else { qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key)); return false; } } return false; } bool ChannelWebAPIUtils::addChannel(unsigned int deviceSetIndex, const QString& uri, int direction) { MainCore *mainCore = MainCore::instance(); PluginAPI::ChannelRegistrations *channelRegistrations = mainCore->getPluginManager()->getRxChannelRegistrations(); int nbRegistrations = channelRegistrations->size(); int index = 0; for (; index < nbRegistrations; index++) { if (channelRegistrations->at(index).m_channelIdURI == uri) { break; } } if (index < nbRegistrations) { MainCore::MsgAddChannel *msg = MainCore::MsgAddChannel::create(deviceSetIndex, index, direction); mainCore->getMainMessageQueue()->push(msg); return true; } else { qWarning() << "ChannelWebAPIUtils::addChannel:" << uri << "plugin not available"; return false; } } // response will be deleted after device is opened. bool ChannelWebAPIUtils::addDevice(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) { return DeviceOpener::open(hwType, direction, settingsKeys, response); } DeviceOpener::DeviceOpener(int deviceIndex, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) : m_deviceIndex(deviceIndex), m_direction(direction), m_settingsKeys(settingsKeys), m_response(response), m_device(nullptr) { connect(MainCore::instance(), &MainCore::deviceSetAdded, this, &DeviceOpener::deviceSetAdded); // Create DeviceSet MainCore *mainCore = MainCore::instance(); m_deviceSetIndex = mainCore->getDeviceSets().size(); MainCore::MsgAddDeviceSet *msg = MainCore::MsgAddDeviceSet::create(m_direction); mainCore->getMainMessageQueue()->push(msg); } void DeviceOpener::deviceSetAdded(int index, DeviceAPI *device) { if (index == m_deviceSetIndex) { disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &DeviceOpener::deviceSetAdded); m_device = device; // Set the correct device type MainCore::MsgSetDevice *msg = MainCore::MsgSetDevice::create(m_deviceSetIndex, m_deviceIndex, m_direction); MainCore::instance()->getMainMessageQueue()->push(msg); // Wait until device has initialised - FIXME: Better way to do this other than polling? m_timer.setInterval(250); connect(&m_timer, &QTimer::timeout, this, &DeviceOpener::checkInitialised); m_timer.start(); } } void DeviceOpener::checkInitialised() { if (m_device && m_device->getSampleSource() && (m_device->state() >= DeviceAPI::EngineState::StIdle)) { m_timer.stop(); QString errorMessage; if (200 != m_device->getSampleSource()->webapiSettingsPutPatch(false, m_settingsKeys, *m_response, errorMessage)) { qDebug() << "DeviceOpener::checkInitialised: webapiSettingsPutPatch failed: " << errorMessage; } delete m_response; delete this; } } bool DeviceOpener::open(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) { if (direction) { return false; // FIXME: Only RX support for now } int nbSamplingDevices = DeviceEnumerator::instance()->getNbRxSamplingDevices(); bool found = false; for (int i = 0; i < nbSamplingDevices; i++) { const PluginInterface::SamplingDevice *samplingDevice; samplingDevice = DeviceEnumerator::instance()->getRxSamplingDevice(i); if (!hwType.isEmpty() && (hwType != samplingDevice->hardwareId)) { continue; } new DeviceOpener(i, direction, settingsKeys, response); return true; } if (!found) { qCritical() << "DeviceOpener::open: Failed to find device with hwType " << hwType; return false; } }