Aaronia RTSA output: initial commit

pull/1697/head
f4exb 2023-05-23 10:23:18 +02:00
rodzic ef5f4c5d9f
commit a6fa12ab3b
32 zmienionych plików z 996 dodań i 152 usunięć

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 21 KiB

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 22 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 17 KiB

Wyświetl plik

@ -5,6 +5,7 @@ set(aaroniartsaoutput_SOURCES
aaroniartsaoutputplugin.cpp
aaroniartsaoutputsettings.cpp
aaroniartsaoutputwebapiadapter.cpp
aaroniartsaoutputworker.cpp
)
set(aaroniartsaoutput_HEADERS
@ -12,6 +13,7 @@ set(aaroniartsaoutput_HEADERS
aaroniartsaoutputplugin.h
aaroniartsaoutputsettings.h
aaroniartsaoutputwebapiadapter.h
aaroniartsaoutputworker.h
)
include_directories(

Wyświetl plik

@ -21,6 +21,7 @@
#include <QDebug>
#include <QNetworkReply>
#include <QBuffer>
#include <QThread>
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
@ -32,18 +33,23 @@
#include "dsp/dspengine.h"
#include "device/deviceapi.h"
#include "aaroniartsaoutputworker.h"
#include "aaroniartsaoutput.h"
MESSAGE_CLASS_DEFINITION(AaroniaRTSAOutput::MsgConfigureAaroniaRTSAOutput, Message)
MESSAGE_CLASS_DEFINITION(AaroniaRTSAOutput::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(AaroniaRTSAOutput::MsgReportSampleRateAndFrequency, Message)
MESSAGE_CLASS_DEFINITION(AaroniaRTSAOutput::MsgSetStatus, Message)
AaroniaRTSAOutput::AaroniaRTSAOutput(DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_settings(),
m_centerFrequency(0),
m_sampleRate(48000),
m_deviceDescription("AaroniaRTSAOutput")
m_deviceDescription("AaroniaRTSAOutput"),
m_worker(nullptr),
m_workerThread(nullptr),
m_running(false)
{
m_sampleSourceFifo.resize(SampleSourceFifo::getSizePolicy(m_sampleRate));
m_deviceAPI->setNbSinkStreams(1);
@ -80,13 +86,53 @@ void AaroniaRTSAOutput::init()
bool AaroniaRTSAOutput::start()
{
QMutexLocker mutexLocker(&m_mutex);
if (m_running) {
return true;
}
qDebug() << "AaroniaRTSAOutput::start";
m_workerThread = new QThread();
m_worker = new AaroniaRTSAOutputWorker(&m_sampleSourceFifo);
m_worker->moveToThread(m_workerThread);
QObject::connect(m_workerThread, &QThread::started, m_worker, &AaroniaRTSAOutputWorker::startWork);
QObject::connect(m_workerThread, &QThread::finished, m_worker, &QObject::deleteLater);
QObject::connect(m_workerThread, &QThread::finished, m_workerThread, &QThread::deleteLater);
QObject::connect(m_worker, &AaroniaRTSAOutputWorker::updateStatus, this, &AaroniaRTSAOutput::setWorkerStatus);
m_workerThread->start();
m_running = true;
mutexLocker.unlock();
applySettings(m_settings, QList<QString>(), true);
qDebug("AaroniaRTSAOutput::start: started");
return true;
}
void AaroniaRTSAOutput::stop()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_running) {
return;
}
qDebug() << "AaroniaRTSAOutput::stop";
m_running = false;
if (m_workerThread)
{
m_worker->stopWork();
m_workerThread->quit();
m_workerThread->wait();
m_worker = nullptr;
m_workerThread = nullptr;
}
}
QByteArray AaroniaRTSAOutput::serialize() const
@ -165,6 +211,13 @@ void AaroniaRTSAOutput::setCenterFrequency(qint64 centerFrequency)
}
}
void AaroniaRTSAOutput::setWorkerStatus(int status)
{
if (m_guiMessageQueue) {
m_guiMessageQueue->push(MsgSetStatus::create(status));
}
}
bool AaroniaRTSAOutput::handleMessage(const Message& message)
{
if (DSPSignalNotification::match(message))
@ -206,13 +259,48 @@ bool AaroniaRTSAOutput::handleMessage(const Message& message)
}
}
int AaroniaRTSAOutput::getStatus() const
{
// TODO
// if (m_aaroniaRTSAWorker) {
// return m_aaroniaRTSAWorker->getStatus();
// } else {
return 0;
// }
}
void AaroniaRTSAOutput::applySettings(const AaroniaRTSAOutputSettings& settings, const QList<QString>& settingsKeys, bool force)
{
qDebug() << "AaroniaRTSAOutput::applySettings: force:" << force << settings.getDebugString(settingsKeys, force);
QMutexLocker mutexLocker(&m_mutex);
std::ostringstream os;
QString remoteAddress;
QList<QString> reverseAPIKeys;
bool forwardChangeToDSP = false;
if (settingsKeys.contains("centerFrequency") || force)
{
if (m_worker) {
m_worker->setCenterFrequency(settings.m_centerFrequency);
}
forwardChangeToDSP = true;
}
if (settingsKeys.contains("sampleRate") || force)
{
if (m_worker) {
m_worker->setSampleRate(settings.m_sampleRate);
}
forwardChangeToDSP = true;
}
if (settingsKeys.contains("serverAddress") || force)
{
if (m_worker) {
m_worker->setServerAddress(settings.m_serverAddress);
}
}
if (settingsKeys.contains("useReverseAPI"))
{
@ -223,13 +311,17 @@ void AaroniaRTSAOutput::applySettings(const AaroniaRTSAOutputSettings& settings,
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
}
if (forwardChangeToDSP)
{
DSPSignalNotification *notif = new DSPSignalNotification(settings.m_sampleRate, settings.m_centerFrequency);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_remoteAddress = remoteAddress;
}
int AaroniaRTSAOutput::webapiRunGet(
@ -299,6 +391,15 @@ void AaroniaRTSAOutput::webapiUpdateDeviceSettings(
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response)
{
if (deviceSettingsKeys.contains("centerFrequency")) {
settings.m_centerFrequency = response.getAaroniaRtsaOutputSettings()->getCenterFrequency();
}
if (deviceSettingsKeys.contains("sampleRate")) {
settings.m_sampleRate = response.getAaroniaRtsaOutputSettings()->getSampleRate();
}
if (deviceSettingsKeys.contains("serverAddress")) {
settings.m_serverAddress = *response.getAaroniaRtsaOutputSettings()->getServerAddress();
}
if (deviceSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getAaroniaRtsaOutputSettings()->getUseReverseApi() != 0;
}
@ -315,6 +416,15 @@ void AaroniaRTSAOutput::webapiUpdateDeviceSettings(
void AaroniaRTSAOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const AaroniaRTSAOutputSettings& settings)
{
response.getAaroniaRtsaOutputSettings()->setCenterFrequency(settings.m_centerFrequency);
response.getAaroniaRtsaOutputSettings()->setSampleRate(settings.m_sampleRate);
if (response.getAaroniaRtsaOutputSettings()->getServerAddress()) {
*response.getAaroniaRtsaOutputSettings()->getServerAddress() = settings.m_serverAddress;
} else {
response.getAaroniaRtsaOutputSettings()->setServerAddress(new QString(settings.m_serverAddress));
}
response.getAaroniaRtsaOutputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getAaroniaRtsaOutputSettings()->getReverseApiAddress()) {
@ -340,8 +450,7 @@ int AaroniaRTSAOutput::webapiReportGet(
void AaroniaRTSAOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
{
response.getAaroniaRtsaOutputReport()->setCenterFrequency(m_centerFrequency);
response.getAaroniaRtsaOutputReport()->setSampleRate(m_sampleRate);
response.getAaroniaRtsaOutputReport()->setStatus(getStatus());
}
void AaroniaRTSAOutput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const AaroniaRTSAOutputSettings& settings, bool force)

Wyświetl plik

@ -15,8 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_LOCALOUTPUT_H
#define INCLUDE_LOCALOUTPUT_H
#ifndef INCLUDE_AARONIARTSAOUTPUT_H
#define INCLUDE_AARONIARTSAOUTPUT_H
#include <ctime>
#include <iostream>
@ -34,6 +34,8 @@
class QNetworkAccessManager;
class QNetworkReply;
class DeviceAPI;
class QThread;
class AaroniaRTSAOutputWorker;
class AaroniaRTSAOutput : public DeviceSampleSink {
Q_OBJECT
@ -104,6 +106,25 @@ public:
{ }
};
class MsgSetStatus : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getStatus() const { return m_status; }
static MsgSetStatus* create(int status) {
return new MsgSetStatus(status);
}
protected:
int m_status;
MsgSetStatus(int status) :
Message(),
m_status(status)
{ }
};
AaroniaRTSAOutput(DeviceAPI *deviceAPI);
virtual ~AaroniaRTSAOutput();
virtual void destroy();
@ -163,11 +184,14 @@ private:
AaroniaRTSAOutputSettings m_settings;
qint64 m_centerFrequency;
int m_sampleRate;
QString m_remoteAddress;
QString m_deviceDescription;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
AaroniaRTSAOutputWorker *m_worker;
QThread *m_workerThread;
bool m_running;
int getStatus() const;
void applySettings(const AaroniaRTSAOutputSettings& settings, const QList<QString>& settingsKeys, bool force = false);
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
void webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const AaroniaRTSAOutputSettings& settings, bool force);
@ -175,6 +199,7 @@ private:
private slots:
void networkManagerFinished(QNetworkReply *reply);
void setWorkerStatus(int status);
};
#endif // INCLUDE_LOCALOUTPUT_H
#endif // INCLUDE_AARONIARTSAOUTPUT_H

Wyświetl plik

@ -62,10 +62,26 @@ AaroniaRTSAOutputGui::AaroniaRTSAOutputGui(DeviceUISet *deviceUISet, QWidget* pa
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
m_statusTooltips.push_back("Idle"); // 0
m_statusTooltips.push_back("Unstable"); // 1
m_statusTooltips.push_back("Connected"); // 2
m_statusTooltips.push_back("Error"); // 3
m_statusTooltips.push_back("Disconnected"); // 4
m_statusColors.push_back("gray"); // Idle
m_statusColors.push_back("rgb(232, 212, 35)"); // Unstable (yellow)
m_statusColors.push_back("rgb(35, 138, 35)"); // Connected (green)
m_statusColors.push_back("rgb(232, 85, 85)"); // Error (red)
m_statusColors.push_back("rgb(232, 85, 232)"); // Disconnected (magenta)
ui->setupUi(getContents());
sizeToContents();
getContents()->setStyleSheet("#AaroniaRTSAOutputGui { background-color: rgb(64, 64, 64); }");
m_helpURL = "plugins/samplesink/localoutput/readme.md";
m_helpURL = "plugins/samplesink/aaroniartsaoutput/readme.md";
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequency->setValueRange(9, 0, 999999999);
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
ui->sampleRate->setValueRange(7, 2000U, 8000000U);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
@ -168,6 +184,28 @@ bool AaroniaRTSAOutputGui::handleMessage(const Message& message)
return true;
}
else if (DSPSignalNotification::match(message))
{
DSPSignalNotification& notif = (DSPSignalNotification&) message;
m_streamSampleRate = notif.getSampleRate();
m_streamCenterFrequency = notif.getCenterFrequency();
qDebug("AaroniaRTSAOutputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu",
notif.getSampleRate(),
notif.getCenterFrequency());
updateSampleRateAndFrequency();
return true;
}
else if (AaroniaRTSAOutput::MsgSetStatus::match(message))
{
qDebug("AaroniaRTSAOutputGui::handleMessage: MsgSetStatus");
AaroniaRTSAOutput::MsgSetStatus& notif = (AaroniaRTSAOutput::MsgSetStatus&) message;
int status = notif.getStatus();
ui->statusIndicator->setToolTip(m_statusTooltips[status]);
ui->statusIndicator->setStyleSheet("QLabel { background-color: " +
m_statusColors[status] + "; border-radius: 7px; }");
return true;
}
else
{
return false;
@ -209,13 +247,12 @@ void AaroniaRTSAOutputGui::handleInputMessages()
}
}
void AaroniaRTSAOutputGui::updateSampleRateAndFrequency()
{
void AaroniaRTSAOutputGui::updateSampleRateAndFrequency(){
m_deviceUISet->getSpectrum()->setSampleRate(m_streamSampleRate);
m_deviceUISet->getSpectrum()->setCenterFrequency(m_streamCenterFrequency);
ui->deviceRateText->setText(tr("%1k").arg((float)m_streamSampleRate / 1000));
blockApplySettings(true);
ui->centerFrequency->setText(QString("%L1").arg(m_streamCenterFrequency / 1000));
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
blockApplySettings(false);
}
@ -223,8 +260,10 @@ void AaroniaRTSAOutputGui::displaySettings()
{
blockApplySettings(true);
ui->centerFrequency->setText(QString("%L1").arg(m_streamCenterFrequency / 1000));
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
ui->sampleRate->setValue(m_settings.m_sampleRate);
ui->deviceRateText->setText(tr("%1k").arg(m_streamSampleRate / 1000.0));
ui->serverAddress->setText(m_settings.m_serverAddress);
blockApplySettings(false);
}
@ -245,6 +284,40 @@ void AaroniaRTSAOutputGui::on_startStop_toggled(bool checked)
}
}
void AaroniaRTSAOutputGui::on_centerFrequency_changed(quint64 value)
{
m_settings.m_centerFrequency = value * 1000;
m_settingsKeys.append("centerFrequency");
sendSettings();
}
void AaroniaRTSAOutputGui::on_sampleRate_changed(quint64 value)
{
m_settings.m_sampleRate = value;
m_settingsKeys.append("sampleRate");
sendSettings();
}
void AaroniaRTSAOutputGui::on_serverAddress_returnPressed()
{
on_serverAddressApplyButton_clicked();
}
void AaroniaRTSAOutputGui::on_serverAddressApplyButton_clicked()
{
QString serverAddress = ui->serverAddress->text();
QUrl url(serverAddress);
if (QStringList{"ws", "wss", "http", "https"}.contains(url.scheme())) {
m_settings.m_serverAddress = QString("%1:%2").arg(url.host()).arg(url.port());
} else {
m_settings.m_serverAddress = serverAddress;
}
m_settingsKeys.append("serverAddress");
sendSettings();
}
void AaroniaRTSAOutputGui::updateHardware()
{
if (m_doApplySettings)
@ -320,4 +393,8 @@ void AaroniaRTSAOutputGui::openDeviceSettingsDialog(const QPoint& p)
void AaroniaRTSAOutputGui::makeUIConnections()
{
QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &AaroniaRTSAOutputGui::on_startStop_toggled);
QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &AaroniaRTSAOutputGui::on_centerFrequency_changed);
QObject::connect(ui->sampleRate, &ValueDial::changed, this, &AaroniaRTSAOutputGui::on_sampleRate_changed);
QObject::connect(ui->serverAddress, &QLineEdit::returnPressed, this, &AaroniaRTSAOutputGui::on_serverAddress_returnPressed);
QObject::connect(ui->serverAddressApplyButton, &QPushButton::clicked, this, &AaroniaRTSAOutputGui::on_serverAddressApplyButton_clicked);
}

Wyświetl plik

@ -15,8 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_LOCALOUTPUTGUI_H
#define INCLUDE_LOCALOUTPUTGUI_H
#ifndef INCLUDE_AARONIARTSAOUTPUTGUI_H
#define INCLUDE_AARONIARTSAOUTPUTGUI_H
#include <QTimer>
#include <QWidget>
@ -70,6 +70,9 @@ private:
QPalette m_paletteGreenText;
QPalette m_paletteWhiteText;
std::vector<QString> m_statusColors;
std::vector<QString> m_statusTooltips;
void blockApplySettings(bool block);
void displaySettings();
void sendSettings();
@ -80,9 +83,13 @@ private:
private slots:
void handleInputMessages();
void on_startStop_toggled(bool checked);
void on_centerFrequency_changed(quint64 value);
void on_sampleRate_changed(quint64 value);
void on_serverAddress_returnPressed();
void on_serverAddressApplyButton_clicked();
void updateHardware();
void updateStatus();
void openDeviceSettingsDialog(const QPoint& p);
};
#endif // INCLUDE_LOCALOUTPUTGUI_H
#endif // INCLUDE_AARONIARTSAOUTPUTGUI_H

Wyświetl plik

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>360</width>
<height>47</height>
<height>130</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,13 +19,13 @@
<property name="minimumSize">
<size>
<width>360</width>
<height>47</height>
<height>130</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>380</width>
<height>68</height>
<height>130</height>
</size>
</property>
<property name="font">
@ -112,24 +112,36 @@
</spacer>
</item>
<item>
<widget class="QLabel" name="centerFrequency">
<widget class="ValueDial" name="centerFrequency" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<family>Liberation Mono</family>
<pointsize>16</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>10,000,000,000</string>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Tuner center frequency in kHz</string>
</property>
</widget>
</item>
@ -142,7 +154,7 @@
</sizepolicy>
</property>
<property name="text">
<string> Hz</string>
<string> kHz</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@ -164,6 +176,130 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="sampleRateLayout">
<property name="topMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="sampleRateLabel">
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
<item>
<widget class="ValueDial" name="sampleRate" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>Device sample rate</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rateUnits">
<property name="text">
<string>S/s</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="serverAddressLayout">
<item>
<widget class="QLabel" name="serverAddressLabel">
<property name="text">
<string>Addr</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="serverAddress">
<property name="toolTip">
<string>Server address</string>
</property>
<property name="text">
<string>127.0.0.1:8073</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusIndicator">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>14</width>
<height>14</height>
</size>
</property>
<property name="toolTip">
<string>Idle</string>
</property>
<property name="styleSheet">
<string notr="true">QLabel { background-color: gray; border-radius: 7px; }</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="serverAddressApplyButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Set</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
@ -172,6 +308,12 @@
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>

Wyświetl plik

@ -30,8 +30,8 @@
const PluginDescriptor AaroniaRTSAOutputPlugin::m_pluginDescriptor = {
QStringLiteral("AaroniaRTSAOutput"),
QStringLiteral("Local device output"),
QStringLiteral("7.8.2"),
QStringLiteral("AaroniaRTSA output"),
QStringLiteral("7.14.0"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
@ -39,7 +39,7 @@ const PluginDescriptor AaroniaRTSAOutputPlugin::m_pluginDescriptor = {
};
static constexpr const char* const m_hardwareID = "AaroniaRTSAOutput";
static constexpr const char* const m_deviceTypeID = LOCALOUTPUT_DEVICE_TYPE_ID;
static constexpr const char* const m_deviceTypeID = AARONIARTSAOUTPUT_DEVICE_TYPE_ID;
AaroniaRTSAOutputPlugin::AaroniaRTSAOutputPlugin(QObject* parent) :
QObject(parent)

Wyświetl plik

@ -15,20 +15,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_LOCALOUTPUTPLUGIN_H
#define INCLUDE_LOCALOUTPUTPLUGIN_H
#ifndef INCLUDE_AARONIARTSAOUTPUTPLUGIN_H
#define INCLUDE_AARONIARTSAOUTPUTPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
#define LOCALOUTPUT_DEVICE_TYPE_ID "sdrangel.samplesink.localoutput"
#define AARONIARTSAOUTPUT_DEVICE_TYPE_ID "sdrangel.samplesink.aaroniartsaoutput"
class PluginAPI;
class AaroniaRTSAOutputPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID LOCALOUTPUT_DEVICE_TYPE_ID)
Q_PLUGIN_METADATA(IID AARONIARTSAOUTPUT_DEVICE_TYPE_ID)
public:
explicit AaroniaRTSAOutputPlugin(QObject* parent = nullptr);
@ -49,4 +49,4 @@ private:
static const PluginDescriptor m_pluginDescriptor;
};
#endif // INCLUDE_LOCALOUTPUTPLUGIN_H
#endif // INCLUDE_AARONIARTSAOUTPUTPLUGIN_H

Wyświetl plik

@ -25,6 +25,9 @@ AaroniaRTSAOutputSettings::AaroniaRTSAOutputSettings()
void AaroniaRTSAOutputSettings::resetToDefaults()
{
m_centerFrequency = 433200000;
m_sampleRate = 100000;
m_serverAddress = "127.0.0.1:5550";
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
@ -35,9 +38,12 @@ QByteArray AaroniaRTSAOutputSettings::serialize() const
{
SimpleSerializer s(1);
s.writeString(4, m_reverseAPIAddress);
s.writeU32(5, m_reverseAPIPort);
s.writeU32(6, m_reverseAPIDeviceIndex);
s.writeU64(1, m_centerFrequency);
s.writeString(2, m_serverAddress);
s.writeS32(3, m_sampleRate);
s.writeString(20, m_reverseAPIAddress);
s.writeU32(21, m_reverseAPIPort);
s.writeU32(22, m_reverseAPIDeviceIndex);
return s.final();
}
@ -56,8 +62,11 @@ bool AaroniaRTSAOutputSettings::deserialize(const QByteArray& data)
{
quint32 uintval;
d.readString(4, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(5, &uintval, 0);
d.readU64(1, &m_centerFrequency, 433200000);
d.readString(2, &m_serverAddress, "127.0.0.1:5550");
d.readS32(3, &m_sampleRate, 100000);
d.readString(20, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(21, &uintval, 0);
if ((uintval > 1023) && (uintval < 65535)) {
m_reverseAPIPort = uintval;
@ -65,7 +74,7 @@ bool AaroniaRTSAOutputSettings::deserialize(const QByteArray& data)
m_reverseAPIPort = 8888;
}
d.readU32(6, &uintval, 0);
d.readU32(22, &uintval, 0);
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
return true;
@ -79,6 +88,15 @@ bool AaroniaRTSAOutputSettings::deserialize(const QByteArray& data)
void AaroniaRTSAOutputSettings::applySettings(const QStringList& settingsKeys, const AaroniaRTSAOutputSettings& settings)
{
if (settingsKeys.contains("centerFrequency")) {
m_centerFrequency = settings.m_centerFrequency;
}
if (settingsKeys.contains("sampleRate")) {
m_sampleRate = settings.m_sampleRate;
}
if (settingsKeys.contains("serverAddress")) {
m_serverAddress = settings.m_serverAddress;
}
if (settingsKeys.contains("useReverseAPI")) {
m_useReverseAPI = settings.m_useReverseAPI;
}
@ -97,6 +115,15 @@ QString AaroniaRTSAOutputSettings::getDebugString(const QStringList& settingsKey
{
std::ostringstream ostr;
if (settingsKeys.contains("centerFrequency") || force) {
ostr << " m_centerFrequency: " << m_centerFrequency;
}
if (settingsKeys.contains("sampleRate") || force) {
ostr << " m_sampleRate: " << m_sampleRate;
}
if (settingsKeys.contains("serverAddress") || force) {
ostr << " m_serverAddress: " << m_serverAddress.toStdString();
}
if (settingsKeys.contains("useReverseAPI") || force) {
ostr << " m_useReverseAPI: " << m_useReverseAPI;
}

Wyświetl plik

@ -15,13 +15,28 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESINK_LOCALOUTPUT_LOCALOUTPUTSETTINGS_H_
#define PLUGINS_SAMPLESINK_LOCALOUTPUT_LOCALOUTPUTSETTINGS_H_
#ifndef PLUGINS_AARONIARTSAOUTPUTSETTINGS_H_
#define PLUGINS_AARONIARTSAOUTPUTSETTINGS_H_
#include <QByteArray>
#include <QString>
struct AaroniaRTSAOutputSettings {
struct AaroniaRTSAOutputSettings
{
enum ConnectionStatus
{
ConnectionIdle, // 0 - gray
ConnectionUnstable, // 1 - yellow
ConnectionOK, // 2 - green
ConnectionError, // 3 - red
ConnectionDisconnected // 4 - magenta
};
quint64 m_centerFrequency;
int m_sampleRate;
QString m_serverAddress;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
@ -35,4 +50,4 @@ struct AaroniaRTSAOutputSettings {
QString getDebugString(const QStringList& settingsKeys, bool force=false) const;
};
#endif /* PLUGINS_SAMPLESINK_LOCALOUTPUT_LOCALOUTPUTSETTINGS_H_ */
#endif /* PLUGINS_AARONIARTSAOUTPUTSETTINGS_H_ */

Wyświetl plik

@ -18,6 +18,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_AARONIARTSAOUTPUTWEBAPIADAPTER_H_
#define PLUGINS_AARONIARTSAOUTPUTWEBAPIADAPTER_H_
#include "device/devicewebapiadapter.h"
#include "aaroniartsaoutputsettings.h"
@ -42,3 +45,5 @@ public:
private:
AaroniaRTSAOutputSettings m_settings;
};
#endif // PLUGINS_AARONIARTSAOUTPUTWEBAPIADAPTER_H_

Wyświetl plik

@ -0,0 +1,183 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QJsonObject>
#include "aaroniartsaoutputsettings.h"
#include "aaroniartsaoutputworker.h"
AaroniaRTSAOutputWorker::AaroniaRTSAOutputWorker(SampleSourceFifo* sampleFifo, QObject* parent) :
QObject(parent),
m_running(false),
m_sampleFifo(sampleFifo),
m_sampleRate(100000),
m_packetsPerSecond(10),
m_samplesArrayInt16(nullptr)
{
m_samplesPerPacket = m_sampleRate / m_packetsPerSecond;
m_networkAccessManager = new QNetworkAccessManager(this);
m_timer = new QTimer(this);
m_timer->setTimerType(Qt::PreciseTimer);
m_centerFrequency = 145000000;
}
AaroniaRTSAOutputWorker::~AaroniaRTSAOutputWorker()
{
if (m_running) {
stopWork();
}
}
void AaroniaRTSAOutputWorker::startWork()
{
qDebug("aroniaRTSAOutputWorker::startWork");
m_samplesPerPacket = m_sampleRate / m_packetsPerSecond;
m_sampleResendTime = 1000 / (m_sampleRate / m_samplesPerPacket) ;
m_streamStartTime = ( QDateTime::currentDateTime().currentMSecsSinceEpoch() );
m_lastPacketEnd = m_streamStartTime / 1000.0;
m_sumSamples = 0;
connect(m_timer, SIGNAL(timeout()), this, SLOT(onGeneratePacket()));
qDebug("AaroniaRTSAOutputWorker::startWork: m_sampleResendTime: %f", m_sampleResendTime);
m_timer->start(m_sampleResendTime); //send period
m_running = true;
}
void AaroniaRTSAOutputWorker::stopWork()
{
qDebug("aroniaRTSAOutputWorker::stopWork");
m_running = false;
m_status = AaroniaRTSAOutputSettings::ConnectionIdle;
emit updateStatus(m_status);
disconnect(m_timer, SIGNAL(timeout()), this, SLOT(onGeneratePacket()));
m_timer->stop();
}
void AaroniaRTSAOutputWorker::setSampleRate(int sampleRate)
{
qDebug("aroniaRTSAOutputWorker::setSampleRate: %d", sampleRate);
if (sampleRate == m_sampleRate) {
return;
}
m_samplesPerPacket = sampleRate / m_packetsPerSecond;
m_sampleResendTime = 1000 / (sampleRate / m_samplesPerPacket) ;
m_timer->start(m_sampleResendTime); //send period
m_sampleRate = sampleRate;
}
void AaroniaRTSAOutputWorker::onGeneratePacket()
{
double sampleTimeUS = 1000000.0 / m_sampleRate;
qint64 deltaT = QDateTime::currentDateTime().currentMSecsSinceEpoch();
deltaT = deltaT - (m_lastPacketEnd*1000);
double ndiff = 1000*((double)deltaT + 1 ) / sampleTimeUS ;
double reawaketime = m_sampleResendTime - (sampleTimeUS*(ndiff - m_samplesPerPacket ))/1000 ;
// qDebug("AaroniaRTSAOutputWorker::onGeneratePacket: %f", reawaketime);
m_timer->setInterval( reawaketime );
double newStart = m_lastPacketEnd;
m_lastPacketEnd = newStart + ((m_samplesPerPacket + 1) * sampleTimeUS)/1000000 ;
double timeOffset = 0.4; //put it into future
buildSamples( newStart + timeOffset , m_lastPacketEnd + timeOffset);
}
void AaroniaRTSAOutputWorker::buildSamples(double startTime, double stopTime)
{
unsigned int iPart1Begin, iPart1End, iPart2Begin, iPart2End;
SampleVector& data = m_sampleFifo->getData();
m_sampleFifo->read(m_samplesPerPacket, iPart1Begin, iPart1End, iPart2Begin, iPart2End);
if (m_samplesArrayInt16 == nullptr) {
m_samplesArrayInt16 = new int16_t[2*m_samplesPerPacket];
}
if (iPart1Begin != iPart1End) {
callbackPart(m_samplesArrayInt16, data, iPart1Begin, iPart1End);
}
if (iPart2Begin != iPart2End) {
callbackPart(&m_samplesArrayInt16[(iPart1End - iPart1Begin)*2], data, iPart2Begin, iPart2End);
}
double startFrequency = m_centerFrequency - m_sampleRate/2;
double endFrequency = m_centerFrequency + m_sampleRate/2;
QJsonDocument jdoc(QJsonObject({
{"startTime", startTime },
{"endTime" , stopTime },
{"startFrequency", startFrequency },
{"endFrequency" , endFrequency },
{"minPower", -2},
{"maxPower" , 2},
{"sampleSize", 2},
{"sampleDepth" , 1},
{"payload", "iq"},
{"format", "int16"},
{"scale", 512.0},
{"unit" , "volt"},
{"samples" , 2*m_samplesPerPacket},
}));
postData(jdoc, m_samplesArrayInt16, 2*m_samplesPerPacket);
}
void AaroniaRTSAOutputWorker::callbackPart(int16_t *buf, SampleVector& data, unsigned int iBegin, unsigned int iEnd)
{
for (unsigned int j = 0, i = iBegin; i < iEnd; j++, i++)
{
buf[2*j] = data[i].m_real;
buf[2*j+1] = data[i].m_imag;
}
}
void AaroniaRTSAOutputWorker::postData(QJsonDocument jdoc, int16_t *samplesArray, int nSamples)
{
QUrl url(tr("http://%1/sample").arg(m_serverAddress));
qDebug() << "AaroniaRTSAOutputWorker::postData:" << url;
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/json"));
QByteArray byteArray = jdoc.toJson(QJsonDocument::Compact);
byteArray.append(0x1e);
byteArray.append(QByteArray::fromRawData(reinterpret_cast<char *>(samplesArray), nSamples*sizeof(int16_t)));
QNetworkReply *networkReply = m_networkAccessManager->post(request, byteArray);
connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
}
void AaroniaRTSAOutputWorker::onError(QNetworkReply::NetworkError)
{
QNetworkReply* nReply = qobject_cast<QNetworkReply*>( sender() );
qDebug() << "AaroniaRTSAOutputWorker::onError: Network Error: " + nReply->errorString();
m_timer->stop();
m_status = AaroniaRTSAOutputSettings::ConnectionError;
emit updateStatus(m_status);
}
void AaroniaRTSAOutputWorker::onFinished(QNetworkReply *reply)
{
if ((m_status != AaroniaRTSAOutputSettings::ConnectionOK) && (reply->error() == QNetworkReply::NoError))
{
m_status = AaroniaRTSAOutputSettings::ConnectionOK;
emit updateStatus(m_status);
}
reply->deleteLater();
}

Wyświetl plik

@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef _AARONIARTSA_AARONIARTSAOUTPUTWORKER_H_
#define _AARONIARTSA_AARONIARTSAOUTPUTWORKER_H_
#include <QTimer>
#include "dsp/samplesourcefifo.h"
#include "util/message.h"
#include <QProcess>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <QJsonDocument>
#include <QObject>
#include "dsp/decimatorsfi.h"
class AaroniaRTSAOutputWorker : public QObject {
Q_OBJECT
public:
enum TxFormat {
FLOAT32,
INT16,
ASCII
};
AaroniaRTSAOutputWorker(SampleSourceFifo* sampleFifo, QObject* parent = nullptr);
~AaroniaRTSAOutputWorker();
void startWork();
void stopWork();
int getStatus() const { return m_status; }
void setServerAddress(const QString& serverAddress) { m_serverAddress = serverAddress; }
void setCenterFrequency(quint64 centerFrequency) { m_centerFrequency = centerFrequency; }
void setSampleRate(int sampleRate);
signals:
void updateStatus(int status);
private:
volatile bool m_running;
QTimer *m_timer;
SampleVector m_samplesBuf;
SampleSourceFifo* m_sampleFifo;
QString m_serverAddress;
quint64 m_centerFrequency;
int m_sampleRate;
int m_status; //!< See GUI for status number detail
QNetworkAccessManager *m_networkAccessManager;
int m_packetsPerSecond;
int m_samplesPerPacket;
TxFormat m_txFormat;
qint64 m_streamStartTime;
quint64 m_sumSamples;
long double m_lastPacketEnd;
double m_sampleResendTime;
int16_t *m_samplesArrayInt16;
void buildSamples(double startTime, double stopTime);
void callbackPart(int16_t *buf, SampleVector& data, unsigned int iBegin, unsigned int iEnd);
void postData(QJsonDocument jdoc, int16_t *samplesArray, int nSamples);
private slots:
void onGeneratePacket();
void onError(QNetworkReply::NetworkError code);
void onFinished(QNetworkReply *);
};
#endif // _AARONIARTSA_AARONIARTSAOUTPUTWORKER_H_

Wyświetl plik

@ -1,14 +1,28 @@
<h1>Local output plugin</h1>
<h1>Aaronia RTSA output plugin</h1>
<h2>Introduction</h2>
This output sample sink plugin sends its samples to a Local Source channel in another device set.
You can use this plugin to interface with a http server block in the Aaronia RTSA suite connected to a Spectran V6 device. It is assumed that you have prior knowledge of the Aaronia RTSA suite software and operation of the Spectran V6 RTSA (Real Time Spectrum Analyzer). However in this context there are some specificities i.e. it assumes that the "mission" (in RTSA suite terms) that is the equivalent of a "configuration" in SDRangel has a `HTTP Server` block followed by an `IQ Modulator` block.
An example flow graph could be the following (Stram Debugger is optional):
![Aaronia RTSA Tx flowgraph](../../../doc/img/aaronia_http_tx.jpg)
You have to check the "Adapt Center Frequency" and "Adapt Sample Rate" options in the IQ modulator settings so that SDRangel can control center frequency and sample rate:
![Aaronia RTSA Tx IQMod settings](../../../doc/img/aaronia_http_tx_iqmod.jpg)
You can obviously run the RTSA suite and SDRangel on the same machine and connect via localhost but there are advantages on a split setup:
- The workload can be split between RTSA suite and SDRangel on two different machines. RTSA suite has to perform the upsampling at a very high sample rate so this is demanding on CPU and latency. Often it is better to run it on its own dedicated machine.
- You can have the RTSA suite run on a machine close to the Spectran. This is in fact mandatory due to the length of the USB cables. And you can run SDRangel on another machine (possibly quite more lightweight) anywhere on the network.
<h2>Interface</h2>
The top and bottom bars of the device window are described [here](../../../sdrgui/device/readme.md)
![SDR Local output plugin GUI](../../../doc/img/LocalOutput_plugin.png)
![Aaronia RTSA output plugin GUI](../../../doc/img/AaroniaRTSAOutput.png)
<h3>1: Start/Stop</h3>
@ -17,10 +31,34 @@ Device start / stop button.
- Blue triangle icon: device is ready and can be started
- Green square icon: device is running and can be stopped
<h3>2: Frequency</h3>
<h3>2: Stream sample rate</h3>
This is the center frequency in Hz sent from the Local Source channel instance and corresponds to the center frequency of transmission.
This is the sample rate of the I/Q stream sent to RTSA suite. It should be equal to the value set in (4)
<h3>3: Stream sample rate</h3>
<h3>3: Frequency</h3>
Stream I/Q sample rate in kS/s
This is the center frequency to which set the IQ modulator center frequency.
<h3>4: Stream sample rate</h3>
Sets the I/Q stream sample rate in S/s
<h3>5: Remote address and port</h3>
This is the remote address and port of the HTTP server block in RTSA suite. The address has to be in the form of an IPv4 address.
Press button (7) to validate your change.
<h3>6: Status indicator</h3>
This ball can take the following colors depending on the status:
* **Gray**: Idle
* **Yellow**: Unstable
* **Green**: Connected
* **Red**: Error
* **Magenta**: Disconnected
<h3>7: Set address</h3>
When you change the address in (5) you have to push this button to validate the change.

Wyświetl plik

@ -282,7 +282,7 @@ bool AaroniaRTSAInput::applySettings(const AaroniaRTSAInputSettings& settings, c
qDebug() << "AaroniaRTSAInput::applySettings: force: "<< force << settings.getDebugString(settingsKeys, force);
if (settingsKeys.contains("serverAddress") || force)
{
{
emit setWorkerServerAddress(settings.m_serverAddress);
}
@ -412,7 +412,7 @@ int AaroniaRTSAInput::webapiReportGet(
QString& errorMessage)
{
(void) errorMessage;
response.setAaroniaSdrReport(new SWGSDRangel::SWGAaroniaRTSAReport());
response.setAaroniaRtsaReport(new SWGSDRangel::SWGAaroniaRTSAReport());
response.getAirspyHfReport()->init();
webapiFormatDeviceReport(response);
return 200;
@ -443,7 +443,7 @@ void AaroniaRTSAInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings
void AaroniaRTSAInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
{
response.getAaroniaSdrReport()->setStatus(getStatus());
response.getAaroniaRtsaReport()->setStatus(getStatus());
}
void AaroniaRTSAInput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const AaroniaRTSAInputSettings& settings, bool force)

Wyświetl plik

@ -2100,18 +2100,28 @@ margin-bottom: 20px;
};
defs.AaroniaRTSAOutputReport = {
"properties" : {
"centerFrequency" : {
"status" : {
"type" : "integer",
"format" : "int64"
},
"sampleRate" : {
"type" : "integer"
"description" : "Connection to RTSA server status:\n * 0 - Idle\n * 1 - Unstable\n * 2 - Connected\n * 3 - Error\n * 4 - Disconnected\n"
}
},
"description" : "AaroniaRTSAOutput"
};
defs.AaroniaRTSAOutputSettings = {
"properties" : {
"centerFrequency" : {
"type" : "integer",
"format" : "int64",
"description" : "Sets the center frequency (Hz) of the distant IQ demodulator"
},
"sampleRate" : {
"type" : "integer",
"description" : "Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator"
},
"serverAddress" : {
"type" : "string",
"description" : "Distant AaroniaRTSA instance URL or IPv4 address with port"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
@ -2132,7 +2142,7 @@ margin-bottom: 20px;
"properties" : {
"status" : {
"type" : "integer",
"description" : "0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected"
"description" : "Connection to RTSA server status:\n * 0 - Idle\n * 1 - Unstable\n * 2 - Connected\n * 3 - Error\n * 4 - Disconnected\n"
}
},
"description" : "AaroniaRTSA"
@ -5276,7 +5286,7 @@ margin-bottom: 20px;
"xtrxMIMOReport" : {
"$ref" : "#/definitions/XtrxMIMOReport"
},
"aaroniaSDRReport" : {
"AaroniaRTSAReport" : {
"$ref" : "#/definitions/AaroniaRTSAReport"
},
"aaroniaRTSAOutputReport" : {
@ -57561,7 +57571,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2023-04-10T20:01:50.318+02:00
Generated 2023-04-22T13:14:49.587+02:00
</div>
</div>
</div>

Wyświetl plik

@ -25,12 +25,28 @@ AaroniaRTSAReport:
description: AaroniaRTSA
properties:
status:
description: 0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected
type: integer
description: >
Connection to RTSA server status:
* 0 - Idle
* 1 - Unstable
* 2 - Connected
* 3 - Error
* 4 - Disconnected
AaroniaRTSAOutputSettings:
description: AaroniaRTSAOutput
properties:
centerFrequency:
description: Sets the center frequency (Hz) of the distant IQ demodulator
type: integer
format: int64
sampleRate:
description: Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator
type: integer
serverAddress:
description: Distant AaroniaRTSA instance URL or IPv4 address with port
type: string
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
@ -44,8 +60,12 @@ AaroniaRTSAOutputSettings:
AaroniaRTSAOutputReport:
description: AaroniaRTSAOutput
properties:
centerFrequency:
type: integer
format: int64
sampleRate:
status:
type: integer
description: >
Connection to RTSA server status:
* 0 - Idle
* 1 - Unstable
* 2 - Connected
* 3 - Error
* 4 - Disconnected

Wyświetl plik

@ -71,7 +71,7 @@ DeviceReport:
$ref: "/doc/swagger/include/Xtrx.yaml#/XtrxOutputReport"
xtrxMIMOReport:
$ref: "/doc/swagger/include/Xtrx.yaml#/XtrxMIMOReport"
aaroniaSDRReport:
AaroniaRTSAReport:
$ref: "/doc/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAReport"
aaroniaRTSAOutputReport:
$ref: "/doc/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAOutputReport"

Wyświetl plik

@ -50,7 +50,13 @@ GS232ControllerSettings:
type: number
format: float
protocol:
description: (0 GS-232, 1 SPID rot2prog)
description: (0 GS-232, 1 SPID rot2prog, 2 rotcltd, 3 DFM)
type: integer
precision:
description: Precision of azimuth and elevation values
type: integer
coordinates:
description: (0 Az/El, 1 X/Y 85, 2 X/Y 30)
type: integer
title:
type: string

Wyświetl plik

@ -25,12 +25,28 @@ AaroniaRTSAReport:
description: AaroniaRTSA
properties:
status:
description: 0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected
type: integer
description: >
Connection to RTSA server status:
* 0 - Idle
* 1 - Unstable
* 2 - Connected
* 3 - Error
* 4 - Disconnected
AaroniaRTSAOutputSettings:
description: AaroniaRTSAOutput
properties:
centerFrequency:
description: Sets the center frequency (Hz) of the distant IQ demodulator
type: integer
format: int64
sampleRate:
description: Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator
type: integer
serverAddress:
description: Distant AaroniaRTSA instance URL or IPv4 address with port
type: string
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
@ -44,8 +60,12 @@ AaroniaRTSAOutputSettings:
AaroniaRTSAOutputReport:
description: AaroniaRTSAOutput
properties:
centerFrequency:
type: integer
format: int64
sampleRate:
status:
type: integer
description: >
Connection to RTSA server status:
* 0 - Idle
* 1 - Unstable
* 2 - Connected
* 3 - Error
* 4 - Disconnected

Wyświetl plik

@ -71,7 +71,7 @@ DeviceReport:
$ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxOutputReport"
xtrxMIMOReport:
$ref: "http://swgserver:8081/api/swagger/include/Xtrx.yaml#/XtrxMIMOReport"
aaroniaSDRReport:
AaroniaRTSAReport:
$ref: "http://swgserver:8081/api/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAReport"
aaroniaRTSAOutputReport:
$ref: "http://swgserver:8081/api/swagger/include/AaroniaRTSA.yaml#/AaroniaRTSAOutputReport"

Wyświetl plik

@ -2100,18 +2100,28 @@ margin-bottom: 20px;
};
defs.AaroniaRTSAOutputReport = {
"properties" : {
"centerFrequency" : {
"status" : {
"type" : "integer",
"format" : "int64"
},
"sampleRate" : {
"type" : "integer"
"description" : "Connection to RTSA server status:\n * 0 - Idle\n * 1 - Unstable\n * 2 - Connected\n * 3 - Error\n * 4 - Disconnected\n"
}
},
"description" : "AaroniaRTSAOutput"
};
defs.AaroniaRTSAOutputSettings = {
"properties" : {
"centerFrequency" : {
"type" : "integer",
"format" : "int64",
"description" : "Sets the center frequency (Hz) of the distant IQ demodulator"
},
"sampleRate" : {
"type" : "integer",
"description" : "Sets the sample rate (S/s) and span (Hz) of the distant IQ demodulator"
},
"serverAddress" : {
"type" : "string",
"description" : "Distant AaroniaRTSA instance URL or IPv4 address with port"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
@ -2132,7 +2142,7 @@ margin-bottom: 20px;
"properties" : {
"status" : {
"type" : "integer",
"description" : "0 for Idle, 1 for Connecting, 2 for Connected, 3 for Error, 4 for Disconnected"
"description" : "Connection to RTSA server status:\n * 0 - Idle\n * 1 - Unstable\n * 2 - Connected\n * 3 - Error\n * 4 - Disconnected\n"
}
},
"description" : "AaroniaRTSA"
@ -5276,7 +5286,7 @@ margin-bottom: 20px;
"xtrxMIMOReport" : {
"$ref" : "#/definitions/XtrxMIMOReport"
},
"aaroniaSDRReport" : {
"AaroniaRTSAReport" : {
"$ref" : "#/definitions/AaroniaRTSAReport"
},
"aaroniaRTSAOutputReport" : {
@ -57561,7 +57571,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2023-04-10T20:01:50.318+02:00
Generated 2023-04-22T13:14:49.587+02:00
</div>
</div>
</div>

Wyświetl plik

@ -28,10 +28,8 @@ SWGAaroniaRTSAOutputReport::SWGAaroniaRTSAOutputReport(QString* json) {
}
SWGAaroniaRTSAOutputReport::SWGAaroniaRTSAOutputReport() {
center_frequency = 0L;
m_center_frequency_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
status = 0;
m_status_isSet = false;
}
SWGAaroniaRTSAOutputReport::~SWGAaroniaRTSAOutputReport() {
@ -40,16 +38,13 @@ SWGAaroniaRTSAOutputReport::~SWGAaroniaRTSAOutputReport() {
void
SWGAaroniaRTSAOutputReport::init() {
center_frequency = 0L;
m_center_frequency_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
status = 0;
m_status_isSet = false;
}
void
SWGAaroniaRTSAOutputReport::cleanup() {
}
SWGAaroniaRTSAOutputReport*
@ -63,9 +58,7 @@ SWGAaroniaRTSAOutputReport::fromJson(QString &json) {
void
SWGAaroniaRTSAOutputReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&center_frequency, pJson["centerFrequency"], "qint64", "");
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
::SWGSDRangel::setValue(&status, pJson["status"], "qint32", "");
}
@ -83,34 +76,21 @@ SWGAaroniaRTSAOutputReport::asJson ()
QJsonObject*
SWGAaroniaRTSAOutputReport::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_center_frequency_isSet){
obj->insert("centerFrequency", QJsonValue(center_frequency));
}
if(m_sample_rate_isSet){
obj->insert("sampleRate", QJsonValue(sample_rate));
if(m_status_isSet){
obj->insert("status", QJsonValue(status));
}
return obj;
}
qint64
SWGAaroniaRTSAOutputReport::getCenterFrequency() {
return center_frequency;
}
void
SWGAaroniaRTSAOutputReport::setCenterFrequency(qint64 center_frequency) {
this->center_frequency = center_frequency;
this->m_center_frequency_isSet = true;
}
qint32
SWGAaroniaRTSAOutputReport::getSampleRate() {
return sample_rate;
SWGAaroniaRTSAOutputReport::getStatus() {
return status;
}
void
SWGAaroniaRTSAOutputReport::setSampleRate(qint32 sample_rate) {
this->sample_rate = sample_rate;
this->m_sample_rate_isSet = true;
SWGAaroniaRTSAOutputReport::setStatus(qint32 status) {
this->status = status;
this->m_status_isSet = true;
}
@ -118,10 +98,7 @@ bool
SWGAaroniaRTSAOutputReport::isSet(){
bool isObjectUpdated = false;
do{
if(m_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_sample_rate_isSet){
if(m_status_isSet){
isObjectUpdated = true; break;
}
}while(false);

Wyświetl plik

@ -41,21 +41,15 @@ public:
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGAaroniaRTSAOutputReport* fromJson(QString &jsonString) override;
qint64 getCenterFrequency();
void setCenterFrequency(qint64 center_frequency);
qint32 getSampleRate();
void setSampleRate(qint32 sample_rate);
qint32 getStatus();
void setStatus(qint32 status);
virtual bool isSet() override;
private:
qint64 center_frequency;
bool m_center_frequency_isSet;
qint32 sample_rate;
bool m_sample_rate_isSet;
qint32 status;
bool m_status_isSet;
};

Wyświetl plik

@ -28,6 +28,12 @@ SWGAaroniaRTSAOutputSettings::SWGAaroniaRTSAOutputSettings(QString* json) {
}
SWGAaroniaRTSAOutputSettings::SWGAaroniaRTSAOutputSettings() {
center_frequency = 0L;
m_center_frequency_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
server_address = nullptr;
m_server_address_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
@ -44,6 +50,12 @@ SWGAaroniaRTSAOutputSettings::~SWGAaroniaRTSAOutputSettings() {
void
SWGAaroniaRTSAOutputSettings::init() {
center_frequency = 0L;
m_center_frequency_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
server_address = new QString("");
m_server_address_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
@ -57,6 +69,11 @@ SWGAaroniaRTSAOutputSettings::init() {
void
SWGAaroniaRTSAOutputSettings::cleanup() {
if(server_address != nullptr) {
delete server_address;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
@ -75,6 +92,12 @@ SWGAaroniaRTSAOutputSettings::fromJson(QString &json) {
void
SWGAaroniaRTSAOutputSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&center_frequency, pJson["centerFrequency"], "qint64", "");
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
::SWGSDRangel::setValue(&server_address, pJson["serverAddress"], "QString", "QString");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
@ -99,6 +122,15 @@ SWGAaroniaRTSAOutputSettings::asJson ()
QJsonObject*
SWGAaroniaRTSAOutputSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_center_frequency_isSet){
obj->insert("centerFrequency", QJsonValue(center_frequency));
}
if(m_sample_rate_isSet){
obj->insert("sampleRate", QJsonValue(sample_rate));
}
if(server_address != nullptr && *server_address != QString("")){
toJsonValue(QString("serverAddress"), server_address, obj, QString("QString"));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
@ -115,6 +147,36 @@ SWGAaroniaRTSAOutputSettings::asJsonObject() {
return obj;
}
qint64
SWGAaroniaRTSAOutputSettings::getCenterFrequency() {
return center_frequency;
}
void
SWGAaroniaRTSAOutputSettings::setCenterFrequency(qint64 center_frequency) {
this->center_frequency = center_frequency;
this->m_center_frequency_isSet = true;
}
qint32
SWGAaroniaRTSAOutputSettings::getSampleRate() {
return sample_rate;
}
void
SWGAaroniaRTSAOutputSettings::setSampleRate(qint32 sample_rate) {
this->sample_rate = sample_rate;
this->m_sample_rate_isSet = true;
}
QString*
SWGAaroniaRTSAOutputSettings::getServerAddress() {
return server_address;
}
void
SWGAaroniaRTSAOutputSettings::setServerAddress(QString* server_address) {
this->server_address = server_address;
this->m_server_address_isSet = true;
}
qint32
SWGAaroniaRTSAOutputSettings::getUseReverseApi() {
return use_reverse_api;
@ -160,6 +222,15 @@ bool
SWGAaroniaRTSAOutputSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(server_address && *server_address != QString("")){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}

Wyświetl plik

@ -42,6 +42,15 @@ public:
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGAaroniaRTSAOutputSettings* fromJson(QString &jsonString) override;
qint64 getCenterFrequency();
void setCenterFrequency(qint64 center_frequency);
qint32 getSampleRate();
void setSampleRate(qint32 sample_rate);
QString* getServerAddress();
void setServerAddress(QString* server_address);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
@ -58,6 +67,15 @@ public:
virtual bool isSet() override;
private:
qint64 center_frequency;
bool m_center_frequency_isSet;
qint32 sample_rate;
bool m_sample_rate_isSet;
QString* server_address;
bool m_server_address_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;

Wyświetl plik

@ -92,8 +92,8 @@ SWGDeviceReport::SWGDeviceReport() {
m_xtrx_output_report_isSet = false;
xtrx_mimo_report = nullptr;
m_xtrx_mimo_report_isSet = false;
aaronia_sdr_report = nullptr;
m_aaronia_sdr_report_isSet = false;
aaronia_rtsa_report = nullptr;
m_aaronia_rtsa_report_isSet = false;
aaronia_rtsa_output_report = nullptr;
m_aaronia_rtsa_output_report_isSet = false;
}
@ -168,8 +168,8 @@ SWGDeviceReport::init() {
m_xtrx_output_report_isSet = false;
xtrx_mimo_report = new SWGXtrxMIMOReport();
m_xtrx_mimo_report_isSet = false;
aaronia_sdr_report = new SWGAaroniaRTSAReport();
m_aaronia_sdr_report_isSet = false;
aaronia_rtsa_report = new SWGAaroniaRTSAReport();
m_aaronia_rtsa_report_isSet = false;
aaronia_rtsa_output_report = new SWGAaroniaRTSAOutputReport();
m_aaronia_rtsa_output_report_isSet = false;
}
@ -270,8 +270,8 @@ SWGDeviceReport::cleanup() {
if(xtrx_mimo_report != nullptr) {
delete xtrx_mimo_report;
}
if(aaronia_sdr_report != nullptr) {
delete aaronia_sdr_report;
if(aaronia_rtsa_report != nullptr) {
delete aaronia_rtsa_report;
}
if(aaronia_rtsa_output_report != nullptr) {
delete aaronia_rtsa_output_report;
@ -353,7 +353,7 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&xtrx_mimo_report, pJson["xtrxMIMOReport"], "SWGXtrxMIMOReport", "SWGXtrxMIMOReport");
::SWGSDRangel::setValue(&aaronia_sdr_report, pJson["aaroniaSDRReport"], "SWGAaroniaRTSAReport", "SWGAaroniaRTSAReport");
::SWGSDRangel::setValue(&aaronia_rtsa_report, pJson["AaroniaRTSAReport"], "SWGAaroniaRTSAReport", "SWGAaroniaRTSAReport");
::SWGSDRangel::setValue(&aaronia_rtsa_output_report, pJson["aaroniaRTSAOutputReport"], "SWGAaroniaRTSAOutputReport", "SWGAaroniaRTSAOutputReport");
@ -469,8 +469,8 @@ SWGDeviceReport::asJsonObject() {
if((xtrx_mimo_report != nullptr) && (xtrx_mimo_report->isSet())){
toJsonValue(QString("xtrxMIMOReport"), xtrx_mimo_report, obj, QString("SWGXtrxMIMOReport"));
}
if((aaronia_sdr_report != nullptr) && (aaronia_sdr_report->isSet())){
toJsonValue(QString("aaroniaSDRReport"), aaronia_sdr_report, obj, QString("SWGAaroniaRTSAReport"));
if((aaronia_rtsa_report != nullptr) && (aaronia_rtsa_report->isSet())){
toJsonValue(QString("AaroniaRTSAReport"), aaronia_rtsa_report, obj, QString("SWGAaroniaRTSAReport"));
}
if((aaronia_rtsa_output_report != nullptr) && (aaronia_rtsa_output_report->isSet())){
toJsonValue(QString("aaroniaRTSAOutputReport"), aaronia_rtsa_output_report, obj, QString("SWGAaroniaRTSAOutputReport"));
@ -800,13 +800,13 @@ SWGDeviceReport::setXtrxMimoReport(SWGXtrxMIMOReport* xtrx_mimo_report) {
}
SWGAaroniaRTSAReport*
SWGDeviceReport::getAaroniaSdrReport() {
return aaronia_sdr_report;
SWGDeviceReport::getAaroniaRtsaReport() {
return aaronia_rtsa_report;
}
void
SWGDeviceReport::setAaroniaSdrReport(SWGAaroniaRTSAReport* aaronia_sdr_report) {
this->aaronia_sdr_report = aaronia_sdr_report;
this->m_aaronia_sdr_report_isSet = true;
SWGDeviceReport::setAaroniaRtsaReport(SWGAaroniaRTSAReport* aaronia_rtsa_report) {
this->aaronia_rtsa_report = aaronia_rtsa_report;
this->m_aaronia_rtsa_report_isSet = true;
}
SWGAaroniaRTSAOutputReport*
@ -920,7 +920,7 @@ SWGDeviceReport::isSet(){
if(xtrx_mimo_report && xtrx_mimo_report->isSet()){
isObjectUpdated = true; break;
}
if(aaronia_sdr_report && aaronia_sdr_report->isSet()){
if(aaronia_rtsa_report && aaronia_rtsa_report->isSet()){
isObjectUpdated = true; break;
}
if(aaronia_rtsa_output_report && aaronia_rtsa_output_report->isSet()){

Wyświetl plik

@ -169,8 +169,8 @@ public:
SWGXtrxMIMOReport* getXtrxMimoReport();
void setXtrxMimoReport(SWGXtrxMIMOReport* xtrx_mimo_report);
SWGAaroniaRTSAReport* getAaroniaSdrReport();
void setAaroniaSdrReport(SWGAaroniaRTSAReport* aaronia_sdr_report);
SWGAaroniaRTSAReport* getAaroniaRtsaReport();
void setAaroniaRtsaReport(SWGAaroniaRTSAReport* aaronia_rtsa_report);
SWGAaroniaRTSAOutputReport* getAaroniaRtsaOutputReport();
void setAaroniaRtsaOutputReport(SWGAaroniaRTSAOutputReport* aaronia_rtsa_output_report);
@ -275,8 +275,8 @@ private:
SWGXtrxMIMOReport* xtrx_mimo_report;
bool m_xtrx_mimo_report_isSet;
SWGAaroniaRTSAReport* aaronia_sdr_report;
bool m_aaronia_sdr_report_isSet;
SWGAaroniaRTSAReport* aaronia_rtsa_report;
bool m_aaronia_rtsa_report_isSet;
SWGAaroniaRTSAOutputReport* aaronia_rtsa_output_report;
bool m_aaronia_rtsa_output_report_isSet;