mirror of
https://github.com/jankae/LibreVNA.git
synced 2025-12-06 07:12:10 +01:00
Add SCPI command to read/write the preferences
This commit is contained in:
parent
aeea13347e
commit
2ba954537b
Binary file not shown.
|
|
@ -272,6 +272,21 @@ Important points when saving/loading setup files through SCPI commands:
|
||||||
206039903350,208939A23350
|
206039903350,208939A23350
|
||||||
\end{example}
|
\end{example}
|
||||||
|
|
||||||
|
\subsubsection{DEVice:PREFerences}
|
||||||
|
This command provides read/write access to the preferences. The recommended way is usually to change the preferences manually in the GUI. But if for some reason that is not an option, this is also possible through the SCPI server. There is no complete documentation for all available preferences, refer to the source code.
|
||||||
|
|
||||||
|
\event{Set a preferences entry}{DEVice:PREFerences <name> <value>}{<name> Name of the preferences entry\\ <value> New value for the preferences entry}
|
||||||
|
\begin{example}
|
||||||
|
:DEV:PREF Startup.ConnectToFirstDevice false
|
||||||
|
\end{example}
|
||||||
|
Most settings take effect immediately but some (such as changing the port for the SCPI server) are only applied when the preferences are saved. Also see command~\ref{DEV:APPLYPREF}.
|
||||||
|
|
||||||
|
\query{Returns a preferences entry}{DEVice:PREFerences? <name>}{<name> Name of the preferences entry}{Current value of the preferences entry}
|
||||||
|
|
||||||
|
\subsubsection{DEVice:APPLYPREFerences}
|
||||||
|
\label{DEV:APPLYPREF}
|
||||||
|
\event{Permanently stores the preferences after a setting has been changed}{DEVice:APPLYPREFerences}{None}
|
||||||
|
|
||||||
\subsubsection{DEVice:MODE}
|
\subsubsection{DEVice:MODE}
|
||||||
\event{Switches the device to the specified mode}{DEVice:MODE <mode>}{<mode>:\\ \hspace{1cm} VNA: set to vector analyzer\\ \hspace{1cm} GEN: set to signal generator\\ \hspace{1cm} SA: set to spectrum analyzer}
|
\event{Switches the device to the specified mode}{DEVice:MODE <mode>}{<mode>:\\ \hspace{1cm} VNA: set to vector analyzer\\ \hspace{1cm} GEN: set to signal generator\\ \hspace{1cm} SA: set to spectrum analyzer}
|
||||||
\begin{example}
|
\begin{example}
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ void Math::DFT::fromJSON(nlohmann::json j)
|
||||||
|
|
||||||
void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
|
void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(begin);
|
||||||
Q_UNUSED(end);
|
Q_UNUSED(end);
|
||||||
if(input->rData().size() < 2) {
|
if(input->rData().size() < 2) {
|
||||||
// not enough input data
|
// not enough input data
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ void TDR::setMode(Mode m)
|
||||||
|
|
||||||
void TDR::inputSamplesChanged(unsigned int begin, unsigned int end)
|
void TDR::inputSamplesChanged(unsigned int begin, unsigned int end)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(begin);
|
||||||
Q_UNUSED(end);
|
Q_UNUSED(end);
|
||||||
if(input->rData().size() >= 2) {
|
if(input->rData().size() >= 2) {
|
||||||
// trigger calculation in thread
|
// trigger calculation in thread
|
||||||
|
|
|
||||||
|
|
@ -136,10 +136,10 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
connect(ui->Xauto, &QCheckBox::toggled, [this, updateXenableState](bool checked) {
|
connect(ui->Xauto, &QCheckBox::toggled, [this, updateXenableState](bool) {
|
||||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||||
});
|
});
|
||||||
connect(ui->XautoDivs, &QCheckBox::toggled, [this, updateXenableState](bool checked) {
|
connect(ui->XautoDivs, &QCheckBox::toggled, [this, updateXenableState](bool) {
|
||||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -155,7 +155,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
||||||
|
|
||||||
XAxisTypeChanged((int) plot->xAxis.getType());
|
XAxisTypeChanged((int) plot->xAxis.getType());
|
||||||
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
|
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
|
||||||
connect(ui->Xlog, &QCheckBox::toggled, [=](bool checked){
|
connect(ui->Xlog, &QCheckBox::toggled, [=](bool){
|
||||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ public:
|
||||||
QMetaType mt(destType);
|
QMetaType mt(destType);
|
||||||
mt.construct(ptr, variant.constData());
|
mt.construct(ptr, variant.constData());
|
||||||
}
|
}
|
||||||
QVariant value() {
|
QVariant value() const {
|
||||||
return QVariant(variant.metaType(), ptr);
|
return QVariant(variant.metaType(), ptr);
|
||||||
}
|
}
|
||||||
void* getPtr(){return ptr;}
|
void* getPtr(){return ptr;}
|
||||||
|
|
|
||||||
|
|
@ -231,50 +231,8 @@ void AppWindow::SetupMenu()
|
||||||
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
||||||
// save previous SCPI settings in case they change
|
// save previous SCPI settings in case they change
|
||||||
auto &p = Preferences::getInstance();
|
auto &p = Preferences::getInstance();
|
||||||
auto SCPIenabled = p.SCPIServer.enabled;
|
|
||||||
auto SCPIport = p.SCPIServer.port;
|
|
||||||
p.edit();
|
p.edit();
|
||||||
// store the updated settings
|
preferencesChanged();
|
||||||
p.store();
|
|
||||||
if(SCPIenabled != p.SCPIServer.enabled || SCPIport != p.SCPIServer.port) {
|
|
||||||
StopTCPServer();
|
|
||||||
if(p.SCPIServer.enabled) {
|
|
||||||
StartTCPServer(p.SCPIServer.port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// averaging mode may have changed, update for all relevant modes
|
|
||||||
for (auto m : modeHandler->getModes())
|
|
||||||
{
|
|
||||||
switch (m->getType())
|
|
||||||
{
|
|
||||||
case Mode::Type::VNA:
|
|
||||||
case Mode::Type::SA:
|
|
||||||
if(p.Acquisition.useMedianAveraging) {
|
|
||||||
m->setAveragingMode(Averaging::Mode::Median);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m->setAveragingMode(Averaging::Mode::Mean);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Mode::Type::SG:
|
|
||||||
case Mode::Type::Last:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// acquisition frequencies may have changed, update
|
|
||||||
// UpdateAcquisitionFrequencies();
|
|
||||||
|
|
||||||
auto active = modeHandler->getActiveMode();
|
|
||||||
if (active)
|
|
||||||
{
|
|
||||||
active->updateGraphColors();
|
|
||||||
if(device) {
|
|
||||||
active->initializeDevice();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->actionAbout, &QAction::triggered, [=](){
|
connect(ui->actionAbout, &QAction::triggered, [=](){
|
||||||
|
|
@ -564,6 +522,32 @@ void AppWindow::SetupSCPI()
|
||||||
ret.chop(1);
|
ret.chop(1);
|
||||||
return ret;
|
return ret;
|
||||||
}));
|
}));
|
||||||
|
scpi_dev->add(new SCPICommand("PREFerences", [=](QStringList params) -> QString {
|
||||||
|
if(params.size() != 2) {
|
||||||
|
return SCPI::getResultName(SCPI::Result::Error);
|
||||||
|
}
|
||||||
|
auto &p = Preferences::getInstance();
|
||||||
|
if(p.set(params[0], QVariant(params[1]))) {
|
||||||
|
return SCPI::getResultName(SCPI::Result::Empty);
|
||||||
|
} else {
|
||||||
|
return SCPI::getResultName(SCPI::Result::Error);
|
||||||
|
}
|
||||||
|
}, [=](QStringList params) -> QString {
|
||||||
|
if(params.size() != 1) {
|
||||||
|
return SCPI::getResultName(SCPI::Result::Error);
|
||||||
|
}
|
||||||
|
auto value = Preferences::getInstance().get(params[0]).toString();
|
||||||
|
if(value.isEmpty()) {
|
||||||
|
// failed to get setting
|
||||||
|
return SCPI::getResultName(SCPI::Result::Error);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}, false));
|
||||||
|
scpi_dev->add(new SCPICommand("APPLYPREFerences", [=](QStringList) -> QString {
|
||||||
|
preferencesChanged();
|
||||||
|
return SCPI::getResultName(SCPI::Result::Empty);
|
||||||
|
}, nullptr));
|
||||||
auto scpi_setup = new SCPINode("SETUP");
|
auto scpi_setup = new SCPINode("SETUP");
|
||||||
scpi_dev->add(scpi_setup);
|
scpi_dev->add(scpi_setup);
|
||||||
scpi_setup->add(new SCPICommand("SAVE", [=](QStringList params) -> QString {
|
scpi_setup->add(new SCPICommand("SAVE", [=](QStringList params) -> QString {
|
||||||
|
|
@ -1022,6 +1006,50 @@ void AppWindow::StopTCPServer()
|
||||||
server = nullptr;
|
server = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppWindow::preferencesChanged()
|
||||||
|
{
|
||||||
|
auto &p = Preferences::getInstance();
|
||||||
|
p.store();
|
||||||
|
if(p.SCPIServer.enabled && !server) {
|
||||||
|
StartTCPServer(p.SCPIServer.port);
|
||||||
|
} else if(!p.SCPIServer.enabled && server) {
|
||||||
|
StopTCPServer();
|
||||||
|
} else if(server && server->getPort() != p.SCPIServer.port) {
|
||||||
|
// still enabled but the port changed -> needs to restart the SCPI server
|
||||||
|
StopTCPServer();
|
||||||
|
StartTCPServer(p.SCPIServer.port);
|
||||||
|
}
|
||||||
|
// averaging mode may have changed, update for all relevant modes
|
||||||
|
for (auto m : modeHandler->getModes())
|
||||||
|
{
|
||||||
|
switch (m->getType())
|
||||||
|
{
|
||||||
|
case Mode::Type::VNA:
|
||||||
|
case Mode::Type::SA:
|
||||||
|
if(p.Acquisition.useMedianAveraging) {
|
||||||
|
m->setAveragingMode(Averaging::Mode::Median);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m->setAveragingMode(Averaging::Mode::Mean);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Mode::Type::SG:
|
||||||
|
case Mode::Type::Last:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto active = modeHandler->getActiveMode();
|
||||||
|
if (active)
|
||||||
|
{
|
||||||
|
active->updateGraphColors();
|
||||||
|
if(device) {
|
||||||
|
active->initializeDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SCPI* AppWindow::getSCPI()
|
SCPI* AppWindow::getSCPI()
|
||||||
{
|
{
|
||||||
return &scpi;
|
return &scpi;
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ private:
|
||||||
void StartTCPServer(int port);
|
void StartTCPServer(int port);
|
||||||
void StopTCPServer();
|
void StopTCPServer();
|
||||||
|
|
||||||
|
// Call whenever the preferences have changed. It stores the updated preferences and applies the changes which do not take effect immediately
|
||||||
|
void preferencesChanged();
|
||||||
|
|
||||||
QStackedWidget *central;
|
QStackedWidget *central;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -531,6 +531,61 @@ nlohmann::json Preferences::toJSON()
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Preferences::set(QString name, QVariant value)
|
||||||
|
{
|
||||||
|
QPointerVariant *ptr = nullptr;
|
||||||
|
for(auto s : descr) {
|
||||||
|
if(s.name == name) {
|
||||||
|
ptr = &s.var;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!ptr) {
|
||||||
|
// check the driver settings
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
for(auto s : driver->driverSpecificSettings()) {
|
||||||
|
if(s.name == name) {
|
||||||
|
ptr = &s.var;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ptr) {
|
||||||
|
try {
|
||||||
|
ptr->setValue(value);
|
||||||
|
return true;
|
||||||
|
} catch (const std::runtime_error&) {
|
||||||
|
// failed to set variable, likely wrong format for the QVariant
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant Preferences::get(QString name)
|
||||||
|
{
|
||||||
|
for(auto &s : descr) {
|
||||||
|
if(s.name == name) {
|
||||||
|
return s.var.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
for(auto &s : driver->driverSpecificSettings()) {
|
||||||
|
if(s.name == name) {
|
||||||
|
return s.var.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// not found
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
void Preferences::nonTrivialParsing()
|
void Preferences::nonTrivialParsing()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ Q_DECLARE_METATYPE(MarkerSymbolStyle);
|
||||||
|
|
||||||
|
|
||||||
class Preferences : public Savable {
|
class Preferences : public Savable {
|
||||||
|
friend class PreferencesDialog;
|
||||||
public:
|
public:
|
||||||
static Preferences& getInstance() {
|
static Preferences& getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
|
|
@ -172,12 +173,16 @@ public:
|
||||||
void fromJSON(nlohmann::json j) override;
|
void fromJSON(nlohmann::json j) override;
|
||||||
nlohmann::json toJSON() override;
|
nlohmann::json toJSON() override;
|
||||||
|
|
||||||
void nonTrivialParsing();
|
bool set(QString name, QVariant value);
|
||||||
void nonTrivialWriting();
|
QVariant get(QString name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Preferences() :
|
Preferences() :
|
||||||
TCPoverride(false) {}
|
TCPoverride(false) {}
|
||||||
|
|
||||||
|
void nonTrivialParsing();
|
||||||
|
void nonTrivialWriting();
|
||||||
|
|
||||||
static Preferences instance;
|
static Preferences instance;
|
||||||
|
|
||||||
// TODO remove settings that have been moved to LibreVNADriver
|
// TODO remove settings that have been moved to LibreVNADriver
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
TCPServer::TCPServer(int port)
|
TCPServer::TCPServer(int port)
|
||||||
{
|
{
|
||||||
|
this->port = port;
|
||||||
qInfo() << "Listening on port" << port;
|
qInfo() << "Listening on port" << port;
|
||||||
socket = nullptr;
|
socket = nullptr;
|
||||||
server.listen(QHostAddress::Any, port);
|
server.listen(QHostAddress::Any, port);
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,14 @@ class TCPServer : public QObject
|
||||||
public:
|
public:
|
||||||
TCPServer(int port);
|
TCPServer(int port);
|
||||||
|
|
||||||
|
int getPort() {return port;}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool send(QString line);
|
bool send(QString line);
|
||||||
signals:
|
signals:
|
||||||
void received(QString line);
|
void received(QString line);
|
||||||
private:
|
private:
|
||||||
|
int port;
|
||||||
QTcpServer server;
|
QTcpServer server;
|
||||||
QTcpSocket *socket;
|
QTcpSocket *socket;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue