Add SCPI command to read/write the preferences

This commit is contained in:
Jan Käberich 2024-06-20 14:40:06 +02:00
parent aeea13347e
commit 2ba954537b
12 changed files with 160 additions and 49 deletions

View file

@ -272,6 +272,21 @@ Important points when saving/loading setup files through SCPI commands:
206039903350,208939A23350
\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}
\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}

View file

@ -128,6 +128,7 @@ void Math::DFT::fromJSON(nlohmann::json j)
void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
{
Q_UNUSED(begin);
Q_UNUSED(end);
if(input->rData().size() < 2) {
// not enough input data

View file

@ -202,6 +202,7 @@ void TDR::setMode(Mode m)
void TDR::inputSamplesChanged(unsigned int begin, unsigned int end)
{
Q_UNUSED(begin);
Q_UNUSED(end);
if(input->rData().size() >= 2) {
// trigger calculation in thread

View file

@ -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);
});
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);
});
@ -155,7 +155,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
XAxisTypeChanged((int) plot->xAxis.getType());
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);
});

View file

@ -18,7 +18,7 @@ public:
QMetaType mt(destType);
mt.construct(ptr, variant.constData());
}
QVariant value() {
QVariant value() const {
return QVariant(variant.metaType(), ptr);
}
void* getPtr(){return ptr;}

View file

@ -231,50 +231,8 @@ void AppWindow::SetupMenu()
connect(ui->actionPreferences, &QAction::triggered, [=](){
// save previous SCPI settings in case they change
auto &p = Preferences::getInstance();
auto SCPIenabled = p.SCPIServer.enabled;
auto SCPIport = p.SCPIServer.port;
p.edit();
// store the updated settings
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();
}
}
preferencesChanged();
});
connect(ui->actionAbout, &QAction::triggered, [=](){
@ -564,6 +522,32 @@ void AppWindow::SetupSCPI()
ret.chop(1);
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");
scpi_dev->add(scpi_setup);
scpi_setup->add(new SCPICommand("SAVE", [=](QStringList params) -> QString {
@ -1022,6 +1006,50 @@ void AppWindow::StopTCPServer()
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()
{
return &scpi;

View file

@ -91,6 +91,9 @@ private:
void StartTCPServer(int port);
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;
struct {

View file

@ -531,6 +531,61 @@ nlohmann::json Preferences::toJSON()
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()
{

View file

@ -44,6 +44,7 @@ Q_DECLARE_METATYPE(MarkerSymbolStyle);
class Preferences : public Savable {
friend class PreferencesDialog;
public:
static Preferences& getInstance() {
return instance;
@ -172,12 +173,16 @@ public:
void fromJSON(nlohmann::json j) override;
nlohmann::json toJSON() override;
void nonTrivialParsing();
void nonTrivialWriting();
bool set(QString name, QVariant value);
QVariant get(QString name);
private:
Preferences() :
TCPoverride(false) {}
void nonTrivialParsing();
void nonTrivialWriting();
static Preferences instance;
// TODO remove settings that have been moved to LibreVNADriver

View file

@ -4,6 +4,7 @@
TCPServer::TCPServer(int port)
{
this->port = port;
qInfo() << "Listening on port" << port;
socket = nullptr;
server.listen(QHostAddress::Any, port);

View file

@ -11,12 +11,14 @@ class TCPServer : public QObject
public:
TCPServer(int port);
int getPort() {return port;}
public slots:
bool send(QString line);
signals:
void received(QString line);
private:
int port;
QTcpServer server;
QTcpSocket *socket;
};