diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.cpp b/plugins/channelrx/radioastronomy/radioastronomygui.cpp
index 4880e4a28..438fd974e 100644
--- a/plugins/channelrx/radioastronomy/radioastronomygui.cpp
+++ b/plugins/channelrx/radioastronomy/radioastronomygui.cpp
@@ -57,6 +57,7 @@
#include "feature/featurewebapiutils.h"
#include "feature/feature.h"
#include "feature/featureset.h"
+#include "webapi/webapiutils.h"
#include "radioastronomy.h"
#include "radioastronomysink.h"
@@ -287,6 +288,10 @@ void RadioAstronomyGUI::resizePowerTable()
ui->powerTable->setItem(row, POWER_COL_SENSOR_1, new QTableWidgetItem("1.0000000"));
ui->powerTable->setItem(row, POWER_COL_SENSOR_2, new QTableWidgetItem("1.0000000"));
ui->powerTable->setItem(row, POWER_COL_UTC, new QTableWidgetItem("15/04/2016 10:17:00"));
+ ui->powerTable->setItem(row, POWER_COL_ROT_AZ, new QTableWidgetItem("359.0"));
+ ui->powerTable->setItem(row, POWER_COL_ROT_EL, new QTableWidgetItem("-90.0"));
+ ui->powerTable->setItem(row, POWER_COL_ROT_AZ_OFF, new QTableWidgetItem("-10.0"));
+ ui->powerTable->setItem(row, POWER_COL_ROT_EL_OFF, new QTableWidgetItem("-10.0"));
ui->powerTable->resizeColumnsToContents();
ui->powerTable->removeRow(row);
}
@@ -635,6 +640,10 @@ void RadioAstronomyGUI::powerMeasurementReceived(FFTMeasurement *fft, bool skipC
QTableWidgetItem* sensor1Item = new QTableWidgetItem();
QTableWidgetItem* sensor2Item = new QTableWidgetItem();
QTableWidgetItem* utcItem = new QTableWidgetItem();
+ QTableWidgetItem* rotAzItem = new QTableWidgetItem();
+ QTableWidgetItem* rotElItem = new QTableWidgetItem();
+ QTableWidgetItem* rotAzOffItem = new QTableWidgetItem();
+ QTableWidgetItem* rotElOffItem = new QTableWidgetItem();
ui->powerTable->setItem(row, POWER_COL_DATE, dateItem);
ui->powerTable->setItem(row, POWER_COL_TIME, timeItem);
@@ -664,6 +673,10 @@ void RadioAstronomyGUI::powerMeasurementReceived(FFTMeasurement *fft, bool skipC
ui->powerTable->setItem(row, POWER_COL_SENSOR_1, sensor1Item);
ui->powerTable->setItem(row, POWER_COL_SENSOR_2, sensor2Item);
ui->powerTable->setItem(row, POWER_COL_UTC, utcItem);
+ ui->powerTable->setItem(row, POWER_COL_ROT_AZ, rotAzItem);
+ ui->powerTable->setItem(row, POWER_COL_ROT_EL, rotElItem);
+ ui->powerTable->setItem(row, POWER_COL_ROT_AZ_OFF, rotAzOffItem);
+ ui->powerTable->setItem(row, POWER_COL_ROT_EL_OFF, rotElOffItem);
ui->powerTable->setSortingEnabled(true);
@@ -696,6 +709,13 @@ void RadioAstronomyGUI::powerMeasurementReceived(FFTMeasurement *fft, bool skipC
airTempItem->setData(Qt::DisplayRole, fft->m_airTemp);
sensor1Item->setData(Qt::DisplayRole, fft->m_sensor[0]);
sensor2Item->setData(Qt::DisplayRole, fft->m_sensor[1]);
+ if (fft->m_rotValid)
+ {
+ rotAzItem->setData(Qt::DisplayRole, fft->m_rotAz);
+ rotElItem->setData(Qt::DisplayRole, fft->m_rotEl);
+ rotAzOffItem->setData(Qt::DisplayRole, fft->m_rotAzOff);
+ rotElOffItem->setData(Qt::DisplayRole, fft->m_rotElOff);
+ }
addToPowerSeries(fft, skipCalcs);
}
@@ -2130,6 +2150,10 @@ RadioAstronomyGUI::RadioAstronomyGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI
ui->powerTable->setItemDelegateForColumn(POWER_COL_VBCRS, new DecimalDelegate(1));
ui->powerTable->setItemDelegateForColumn(POWER_COL_VLSR, new DecimalDelegate(1));
ui->powerTable->setItemDelegateForColumn(POWER_COL_AIR_TEMP, new DecimalDelegate(1));
+ ui->powerTable->setItemDelegateForColumn(POWER_COL_ROT_AZ, new DecimalDelegate(0));
+ ui->powerTable->setItemDelegateForColumn(POWER_COL_ROT_EL, new DecimalDelegate(0));
+ ui->powerTable->setItemDelegateForColumn(POWER_COL_ROT_AZ_OFF, new DecimalDelegate(0));
+ ui->powerTable->setItemDelegateForColumn(POWER_COL_ROT_EL_OFF, new DecimalDelegate(0));
resizeSpectrumMarkerTable();
ui->spectrumMarkerTable->setItemDelegateForColumn(SPECTRUM_MARKER_COL_FREQ, new DecimalDelegate(6));
@@ -2733,12 +2757,20 @@ void RadioAstronomyGUI::setColumnPrecisionFromRotator()
((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_GAL_LON))->setPrecision(precision);
((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_AZ))->setPrecision(precision);
((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_EL))->setPrecision(precision);
+ ((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_ROT_AZ))->setPrecision(precision);
+ ((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_ROT_EL))->setPrecision(precision);
+ ((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_ROT_AZ_OFF))->setPrecision(precision);
+ ((DecimalDelegate *)ui->powerTable->itemDelegateForColumn(POWER_COL_ROT_EL_OFF))->setPrecision(precision);
if (precision > old)
{
ui->powerTable->resizeColumnToContents(POWER_COL_GAL_LAT);
ui->powerTable->resizeColumnToContents(POWER_COL_GAL_LON);
ui->powerTable->resizeColumnToContents(POWER_COL_AZ);
ui->powerTable->resizeColumnToContents(POWER_COL_EL);
+ ui->powerTable->resizeColumnToContents(POWER_COL_ROT_AZ);
+ ui->powerTable->resizeColumnToContents(POWER_COL_ROT_EL);
+ ui->powerTable->resizeColumnToContents(POWER_COL_ROT_AZ_OFF);
+ ui->powerTable->resizeColumnToContents(POWER_COL_ROT_EL_OFF);
}
ui->powerTable->viewport()->update();
}
@@ -3712,6 +3744,8 @@ void RadioAstronomyGUI::calCompletetReceived(const RadioAstronomy::MsgCalComplet
}
fft->m_tSys0 = calcTSys0();
fft->m_baseline = m_settings.m_spectrumBaseline;
+ getRotatorData(fft);
+
if (!hot) {
ui->calTsky->setText(QString::number(m_skyTemp, 'f', 1));
@@ -4650,6 +4684,66 @@ void RadioAstronomyGUI::addFFT(FFTMeasurement *fft, bool skipCalcs)
}
}
+void RadioAstronomyGUI::getRotatorData(FFTMeasurement *fft)
+{
+ const QRegExp re("F([0-9]+):([0-9]+)");
+ if (re.indexIn(m_settings.m_rotator) >= 0)
+ {
+ int rotatorFeatureSetIndex = re.capturedTexts()[1].toInt();
+ int rotatorFeatureIndex = re.capturedTexts()[2].toInt();
+
+ SWGSDRangel::SWGFeatureReport featureReport;
+ double value;
+ qDebug() << m_settings.m_rotator << rotatorFeatureSetIndex << rotatorFeatureIndex;
+
+ if (ChannelWebAPIUtils::getFeatureReport(rotatorFeatureSetIndex, rotatorFeatureIndex, featureReport))
+ {
+ QJsonObject *jsonObj = featureReport.asJsonObject();
+ qDebug() << *jsonObj;
+ if (WebAPIUtils::getSubObjectDouble(*jsonObj, "currentAzimuth", value)) {
+ fft->m_rotAz = value;
+ } else {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getSubObjectDouble currentAzimuth failed";
+ }
+ if (WebAPIUtils::getSubObjectDouble(*jsonObj, "currentElevation", value)) {
+ fft->m_rotEl = value;
+ } else {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getSubObjectDouble currentElevation failed";
+ }
+ }
+ else
+ {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getFeatureReport failed";
+ }
+
+ SWGSDRangel::SWGFeatureSettings featureSettingsResponse;
+ Feature *feature;
+ if (ChannelWebAPIUtils::getFeatureSettings(rotatorFeatureSetIndex, rotatorFeatureIndex, featureSettingsResponse, feature))
+ {
+ QJsonObject *jsonObj = featureSettingsResponse.asJsonObject();
+ qDebug() << *jsonObj;
+ if (WebAPIUtils::getSubObjectDouble(*jsonObj, "azimuthOffset", value)) {
+ fft->m_rotAzOff = value;
+ } else {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getSubObjectDouble azimuthOffset failed";
+ }
+ if (WebAPIUtils::getSubObjectDouble(*jsonObj, "elevationOffset", value)) {
+ fft->m_rotElOff = value;
+ } else {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getSubObjectDouble elevationOffset ";
+ }
+ }
+ else
+ {
+ qDebug() << "RadioAstronomyGUI::getRotatorData: getFeatureSettings failed";
+ }
+
+ fft->m_rotValid = true;
+ }
+ else
+ qDebug() << "Couldn't parse rotator feature " << m_settings.m_rotator;
+}
+
void RadioAstronomyGUI::fftMeasurementReceived(const RadioAstronomy::MsgFFTMeasurement& measurement)
{
FFTMeasurement *fft = new FFTMeasurement();
@@ -4681,6 +4775,7 @@ void RadioAstronomyGUI::fftMeasurementReceived(const RadioAstronomy::MsgFFTMeasu
fft->m_sweepIndex = m_sweepIndex++;
fft->m_tSys0 = calcTSys0();
fft->m_baseline = m_settings.m_spectrumBaseline;
+ getRotatorData(fft);
calcFFTPower(fft);
calcFFTTotalPower(fft);
diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.h b/plugins/channelrx/radioastronomy/radioastronomygui.h
index 96fcdd595..9c59404a8 100644
--- a/plugins/channelrx/radioastronomy/radioastronomygui.h
+++ b/plugins/channelrx/radioastronomy/radioastronomygui.h
@@ -98,6 +98,12 @@ class RadioAstronomyGUI : public ChannelGUI {
float m_skyTemp;
float m_sensor[RADIOASTRONOMY_SENSORS];
+ bool m_rotValid;
+ float m_rotAz;
+ float m_rotEl;
+ float m_rotAzOff;
+ float m_rotElOff;
+
int m_sweepIndex;
FFTMeasurement() :
@@ -121,6 +127,11 @@ class RadioAstronomyGUI : public ChannelGUI {
m_coordsValid(false),
m_airTemp(0.0),
m_skyTemp(0.0),
+ m_rotValid(false),
+ m_rotAz(0.0),
+ m_rotEl(0.0),
+ m_rotAzOff(0.0),
+ m_rotElOff(0.0),
m_sweepIndex(0)
{
}
@@ -450,6 +461,7 @@ private:
void calcSpectrumChartTickCount(QValueAxis *axis, int width);
int powerYUnitsToIndex(RadioAstronomySettings::PowerYUnits units);
void setColumnPrecisionFromRotator();
+ void getRotatorData(FFTMeasurement *fft);
void leaveEvent(QEvent*);
void enterEvent(EnterEventType*);
@@ -487,7 +499,11 @@ private:
POWER_COL_AIR_TEMP,
POWER_COL_SENSOR_1,
POWER_COL_SENSOR_2,
- POWER_COL_UTC
+ POWER_COL_UTC,
+ POWER_COL_ROT_AZ,
+ POWER_COL_ROT_EL,
+ POWER_COL_ROT_AZ_OFF,
+ POWER_COL_ROT_EL_OFF
};
enum PowerMarkerTable {
diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.ui b/plugins/channelrx/radioastronomy/radioastronomygui.ui
index e25ea3f5b..fa9e6f11d 100644
--- a/plugins/channelrx/radioastronomy/radioastronomygui.ui
+++ b/plugins/channelrx/radioastronomy/radioastronomygui.ui
@@ -5147,6 +5147,38 @@ This should be close to the expected difference in power between hot and cold ca
UTC date and time measurement finished
+
+
+ Az (Rot)
+
+
+ Azimuth of rotator controller in degrees
+
+
+
+
+ El (Rot)
+
+
+ Elevation of rotator controller in degrees
+
+
+
+
+ Az Off (Rot)
+
+
+ Azimuth offset of rotator controller in degrees
+
+
+
+
+ El Off (Rot)
+
+
+ Elevation offset of rotator controller in degrees
+
+
diff --git a/plugins/channelrx/radioastronomy/radioastronomysettings.h b/plugins/channelrx/radioastronomy/radioastronomysettings.h
index ce03d2c3c..02f8e447a 100644
--- a/plugins/channelrx/radioastronomy/radioastronomysettings.h
+++ b/plugins/channelrx/radioastronomy/radioastronomysettings.h
@@ -28,7 +28,7 @@
class Serializable;
// Number of columns in the tables
-#define RADIOASTRONOMY_POWERTABLE_COLUMNS 28
+#define RADIOASTRONOMY_POWERTABLE_COLUMNS 32
// Number of sensors
#define RADIOASTRONOMY_SENSORS 2
diff --git a/plugins/channelrx/radioastronomy/readme.md b/plugins/channelrx/radioastronomy/readme.md
index 5bd31e942..8b20b3c29 100644
--- a/plugins/channelrx/radioastronomy/readme.md
+++ b/plugins/channelrx/radioastronomy/readme.md
@@ -792,6 +792,10 @@ The columns in the table include:
- Sensor 1 - Data recorded for Sensor 1.
- Sensor 2 - Data recorded for Sensor 2.
- UTC - UTC date and time at the end of the measurement.
+- Az (Rot) - Azimuth of rotator controller in degrees at the end of measurement.
+- El (Rot) - Elevation of rotator controller in degrees at the end of measurement.
+- Az Off (Rot) - Azimimuth offset of rotator controller in degrees at the end of measurement.
+- El Off (Rot) - Elevation offset of rotator controller in degrees at the end of measurement.
Right clicking on the table shows a popup menu that supports:
diff --git a/plugins/feature/startracker/startrackergui.cpp b/plugins/feature/startracker/startrackergui.cpp
index 3d54ac354..97cadbe44 100644
--- a/plugins/feature/startracker/startrackergui.cpp
+++ b/plugins/feature/startracker/startrackergui.cpp
@@ -108,9 +108,7 @@ bool StarTrackerGUI::handleMessage(const Message& message)
m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings());
}
- blockApplySettings(true);
displaySettings();
- blockApplySettings(false);
return true;
}
@@ -118,8 +116,10 @@ bool StarTrackerGUI::handleMessage(const Message& message)
{
StarTrackerReport::MsgReportAzAl& azAl = (StarTrackerReport::MsgReportAzAl&) message;
blockApplySettings(true);
+ blockPlotChart();
ui->azimuth->setValue(azAl.getAzimuth());
ui->elevation->setValue(azAl.getElevation());
+ unblockPlotChartAndPlot();
blockApplySettings(false);
return true;
}
@@ -131,8 +131,10 @@ bool StarTrackerGUI::handleMessage(const Message& message)
{
m_settings.m_ra = Units::decimalHoursToHoursMinutesAndSeconds(raDec.getRA());
m_settings.m_dec = Units::decimalDegreesToDegreeMinutesAndSeconds(raDec.getDec());
+ blockPlotChart();
ui->rightAscension->setText(m_settings.m_ra);
ui->declination->setText(m_settings.m_dec);
+ unblockPlotChartAndPlot();
}
else if (target == "sun")
{
@@ -151,8 +153,10 @@ bool StarTrackerGUI::handleMessage(const Message& message)
{
StarTrackerReport::MsgReportGalactic& galactic = (StarTrackerReport::MsgReportGalactic&) message;
blockApplySettings(true);
+ blockPlotChart();
ui->galacticLongitude->setValue(galactic.getL());
ui->galacticLatitude->setValue(galactic.getB());
+ unblockPlotChartAndPlot();
blockApplySettings(false);
return true;
}
@@ -166,8 +170,10 @@ bool StarTrackerGUI::handleMessage(const Message& message)
QDateTime dt = QDateTime::fromString(*swgSettings->getDateTime(), Qt::ISODateWithMs);
ui->dateTime->setDateTime(dt);
ui->target->setCurrentText("Custom Az/El");
+ blockPlotChart();
ui->azimuth->setValue(swgSettings->getAzimuth());
ui->elevation->setValue(swgSettings->getElevation());
+ unblockPlotChartAndPlot();
}
return true;
}
@@ -304,6 +310,7 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet,
m_pluginAPI(pluginAPI),
m_featureUISet(featureUISet),
m_doApplySettings(true),
+ m_doPlotChart(true),
m_lastFeatureState(0),
m_azElLineChart(nullptr),
m_azElPolarChart(nullptr),
@@ -399,6 +406,7 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet,
ui->dateTime->setDateTime(QDateTime::currentDateTime());
displaySettings();
applySettings(true);
+ disconnect(ui->azimuth, SIGNAL(valueChanged(double)), this, SLOT(on_azimuth_valueChanged(double)));
makeUIConnections();
// Populate subchart menu
@@ -471,12 +479,24 @@ void StarTrackerGUI::blockApplySettings(bool block)
m_doApplySettings = !block;
}
+void StarTrackerGUI::blockPlotChart()
+{
+ m_doPlotChart = false;
+}
+
+void StarTrackerGUI::unblockPlotChartAndPlot()
+{
+ m_doPlotChart = true;
+ plotChart();
+}
+
void StarTrackerGUI::displaySettings()
{
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_settings.m_title);
setTitle(m_settings.m_title);
blockApplySettings(true);
+ blockPlotChart();
ui->darkTheme->setChecked(m_settings.m_chartsDarkTheme);
if (m_solarFluxChart) {
@@ -536,7 +556,7 @@ void StarTrackerGUI::displaySettings()
ui->beamwidth->setValue(m_settings.m_beamwidth);
updateForTarget();
getRollupContents()->restoreState(m_rollupState);
- plotChart();
+ unblockPlotChartAndPlot();
blockApplySettings(false);
}
@@ -923,6 +943,9 @@ void StarTrackerGUI::on_dateTime_dateTimeChanged(const QDateTime &datetime)
void StarTrackerGUI::plotChart()
{
+ if (!m_doPlotChart) {
+ return;
+ }
if (ui->chartSelect->currentIndex() == 0)
{
if (ui->chartSubSelect->currentIndex() == 0) {
@@ -1647,32 +1670,8 @@ void StarTrackerGUI::plotElevationLineChart()
maxElevation = aa.alt;
}
- // Adjust for refraction
- if (m_settings.m_refraction == "Positional Astronomy Library")
- {
- aa.alt += Astronomy::refractionPAL(
- aa.alt,
- m_settings.m_pressure,
- m_settings.m_temperature,
- m_settings.m_humidity,
- m_settings.m_frequency,
- m_settings.m_latitude,
- m_settings.m_heightAboveSeaLevel,
- m_settings.m_temperatureLapseRate
- );
-
- if (aa.alt > 90.0) {
- aa.alt = 90.0f;
- }
- }
- else if (m_settings.m_refraction == "Saemundsson")
- {
- aa.alt += Astronomy::refractionSaemundsson(aa.alt, m_settings.m_pressure, m_settings.m_temperature);
-
- if (aa.alt > 90.0) {
- aa.alt = 90.0f;
- }
- }
+ // Skip adjusting for refraction, as it's too slow to calculate using Astronomy::refractionPAL
+ // in this loop, and doesn't typically make a visible difference in the chart
if (step == 0) {
prevAz = aa.az;
@@ -1857,32 +1856,8 @@ void StarTrackerGUI::plotElevationPolarChart()
maxElevation = aa.alt;
}
- // Adjust for refraction
- if (m_settings.m_refraction == "Positional Astronomy Library")
- {
- aa.alt += Astronomy::refractionPAL(
- aa.alt,
- m_settings.m_pressure,
- m_settings.m_temperature,
- m_settings.m_humidity,
- m_settings.m_frequency,
- m_settings.m_latitude,
- m_settings.m_heightAboveSeaLevel,
- m_settings.m_temperatureLapseRate
- );
-
- if (aa.alt > 90.0) {
- aa.alt = 90.0f;
- }
- }
- else if (m_settings.m_refraction == "Saemundsson")
- {
- aa.alt += Astronomy::refractionSaemundsson(aa.alt, m_settings.m_pressure, m_settings.m_temperature);
-
- if (aa.alt > 90.0) {
- aa.alt = 90.0f;
- }
- }
+ // Skip adjusting for refraction, as it's too slow to calculate using Astronomy::refractionPAL
+ // in this loop, and doesn't typically make a visible difference in the chart
if (idx == 0) {
prevAlt = aa.alt;
diff --git a/plugins/feature/startracker/startrackergui.h b/plugins/feature/startracker/startrackergui.h
index 1186121b8..b3425b5a7 100644
--- a/plugins/feature/startracker/startrackergui.h
+++ b/plugins/feature/startracker/startrackergui.h
@@ -81,6 +81,7 @@ private:
QList m_settingsKeys;
RollupState m_rollupState;
bool m_doApplySettings;
+ bool m_doPlotChart;
StarTracker* m_starTracker;
MessageQueue m_inputMessageQueue;
@@ -135,6 +136,8 @@ private:
virtual ~StarTrackerGUI();
void blockApplySettings(bool block);
+ void blockPlotChart();
+ void unblockPlotChartAndPlot();
void applySettings(bool force = false);
void displaySettings();
void updateForTarget();
diff --git a/plugins/feature/startracker/startrackerworker.cpp b/plugins/feature/startracker/startrackerworker.cpp
index 200361ed1..513bdacdf 100644
--- a/plugins/feature/startracker/startrackerworker.cpp
+++ b/plugins/feature/startracker/startrackerworker.cpp
@@ -519,8 +519,6 @@ void StarTrackerWorker::update()
else
qDebug() << "StarTrackerWorker::update - Failed to parse feature name " << m_settings.m_target;
}
- else
- qDebug() << "TARGET IS NOT SAT TRACKER!! " << m_settings.m_target;
if (m_settings.m_target == "Sun")
{
diff --git a/sdrbase/channel/channelwebapiutils.h b/sdrbase/channel/channelwebapiutils.h
index 1f2f8f9b4..cce4fe7e4 100644
--- a/sdrbase/channel/channelwebapiutils.h
+++ b/sdrbase/channel/channelwebapiutils.h
@@ -81,13 +81,13 @@ public:
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, int &value);
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, double &value);
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, QString &value);
-protected:
static bool getDeviceSettings(unsigned int deviceIndex, SWGSDRangel::SWGDeviceSettings &deviceSettingsResponse, DeviceSet *&deviceSet);
static bool getDeviceReport(unsigned int deviceIndex, SWGSDRangel::SWGDeviceReport &deviceReport);
static bool getFeatureSettings(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureSettings &featureSettingsResponse, Feature *&feature);
static bool getFeatureReport(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureReport &featureReport);
static bool getChannelSettings(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelSettings &channelSettingsResponse, ChannelAPI *&channel);
static bool getChannelReport(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelReport &channelReport);
+protected:
static QString getDeviceHardwareId(unsigned int deviceIndex);
};