2022-10-01 17:10:44 +02:00
|
|
|
#include "scpi.h"
|
|
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
|
|
SCPI::SCPI() :
|
|
|
|
|
SCPINode("")
|
|
|
|
|
{
|
2024-04-07 14:11:04 +02:00
|
|
|
WAIexecuting = false;
|
2024-04-12 12:23:54 +02:00
|
|
|
OPCsetBitScheduled = false;
|
2024-04-07 14:11:04 +02:00
|
|
|
OPCQueryScheduled = false;
|
|
|
|
|
OCAS = false;
|
2024-04-07 14:39:27 +02:00
|
|
|
SESR = 0x00;
|
|
|
|
|
ESE = 0xFF;
|
|
|
|
|
|
|
|
|
|
add(new SCPICommand("*CLS", [=](QStringList) {
|
|
|
|
|
SESR = 0x00;
|
|
|
|
|
OCAS = false;
|
|
|
|
|
OPCQueryScheduled = false;
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
}, nullptr));
|
|
|
|
|
|
|
|
|
|
add(new SCPICommand("*ESE", [=](QStringList params){
|
|
|
|
|
unsigned long long newval;
|
|
|
|
|
if(!SCPI::paramToULongLong(params, 0, newval) || newval >= 256) {
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
} else {
|
|
|
|
|
ESE = newval;
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
}
|
|
|
|
|
}, [=](QStringList){
|
|
|
|
|
return QString::number(ESE);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
add(new SCPICommand("*ESR", nullptr, [=](QStringList){
|
|
|
|
|
auto ret = QString::number(SESR);
|
|
|
|
|
SESR = 0x00;
|
|
|
|
|
return ret;
|
|
|
|
|
}));
|
2024-04-07 14:11:04 +02:00
|
|
|
|
|
|
|
|
add(new SCPICommand("*OPC", [=](QStringList){
|
|
|
|
|
// OPC command
|
|
|
|
|
if(isOperationPending()) {
|
2024-04-12 12:23:54 +02:00
|
|
|
OPCsetBitScheduled = true;
|
2024-04-07 14:11:04 +02:00
|
|
|
OCAS = true;
|
2024-04-07 14:39:27 +02:00
|
|
|
} else {
|
|
|
|
|
// operation already complete
|
|
|
|
|
setFlag(Flag::OPC);
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
}, [=](QStringList) -> QString {
|
|
|
|
|
// OPC query
|
|
|
|
|
if(isOperationPending()) {
|
|
|
|
|
// operation pending
|
|
|
|
|
OPCQueryScheduled = true;
|
|
|
|
|
OCAS = true;
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
} else {
|
|
|
|
|
// no operation, can return immediately
|
|
|
|
|
OCAS = false;
|
|
|
|
|
return "1";
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
add(new SCPICommand("*WAI", [=](QStringList){
|
|
|
|
|
// WAI command
|
|
|
|
|
if(isOperationPending()) {
|
|
|
|
|
WAIexecuting = true;
|
|
|
|
|
}
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
}, nullptr));
|
|
|
|
|
|
2022-10-01 17:10:44 +02:00
|
|
|
add(new SCPICommand("*LST", nullptr, [=](QStringList){
|
|
|
|
|
QString list;
|
|
|
|
|
createCommandList("", list);
|
|
|
|
|
return list.trimmed();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::match(QString s1, QString s2)
|
|
|
|
|
{
|
|
|
|
|
if (s1.compare(s2, Qt::CaseInsensitive) == 0
|
|
|
|
|
|| s1.compare(alternateName(s2), Qt::CaseInsensitive) == 0
|
2022-11-26 09:16:32 +01:00
|
|
|
|| alternateName(s1).compare(s2, Qt::CaseInsensitive) == 0
|
2022-10-01 17:10:44 +02:00
|
|
|
|| alternateName(s1).compare(alternateName(s2), Qt::CaseInsensitive) == 0) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SCPI::alternateName(QString name)
|
|
|
|
|
{
|
|
|
|
|
while(name.size() > 0 && name[name.size()-1].isLower()) {
|
|
|
|
|
name.chop(1);
|
|
|
|
|
}
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::paramToDouble(QStringList params, int index, double &dest)
|
|
|
|
|
{
|
|
|
|
|
if(index >= params.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool okay;
|
|
|
|
|
dest = params[index].toDouble(&okay);
|
|
|
|
|
return okay;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::paramToULongLong(QStringList params, int index, unsigned long long &dest)
|
|
|
|
|
{
|
|
|
|
|
if(index >= params.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-04-12 12:23:54 +02:00
|
|
|
double res;
|
|
|
|
|
bool okay = paramToDouble(params, index, res);
|
|
|
|
|
if(res > std::numeric_limits<unsigned long long>::max() || res < std::numeric_limits<unsigned long long>::min()) {
|
|
|
|
|
okay = false;
|
|
|
|
|
}
|
|
|
|
|
if(okay) {
|
|
|
|
|
dest = res;
|
|
|
|
|
}
|
2022-10-01 17:10:44 +02:00
|
|
|
return okay;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::paramToLong(QStringList params, int index, long &dest)
|
|
|
|
|
{
|
|
|
|
|
if(index >= params.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-04-12 12:23:54 +02:00
|
|
|
double res;
|
|
|
|
|
bool okay = paramToDouble(params, index, res);
|
|
|
|
|
if(res > std::numeric_limits<long>::max() || res < std::numeric_limits<long>::min()) {
|
|
|
|
|
okay = false;
|
|
|
|
|
}
|
|
|
|
|
if(okay) {
|
|
|
|
|
dest = res;
|
|
|
|
|
}
|
2022-10-01 17:10:44 +02:00
|
|
|
return okay;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::paramToBool(QStringList params, int index, bool &dest)
|
|
|
|
|
{
|
|
|
|
|
if(index >= params.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool okay = false;
|
2024-04-12 12:23:54 +02:00
|
|
|
if(params[index] == "TRUE" || params[index] == "ON" || params[index] == "1") {
|
2022-10-01 17:10:44 +02:00
|
|
|
dest = true;
|
|
|
|
|
okay = true;
|
2024-04-12 12:23:54 +02:00
|
|
|
} else if(params[index] == "FALSE" || params[index] == "OFF" || params[index] == "0") {
|
2022-10-01 17:10:44 +02:00
|
|
|
dest = false;
|
|
|
|
|
okay = true;
|
|
|
|
|
}
|
|
|
|
|
return okay;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SCPI::getResultName(SCPI::Result r)
|
|
|
|
|
{
|
|
|
|
|
switch (r) {
|
|
|
|
|
case Result::Empty:
|
|
|
|
|
return "";
|
|
|
|
|
case Result::Error:
|
|
|
|
|
default:
|
|
|
|
|
return "ERROR";
|
2024-04-07 14:22:57 +02:00
|
|
|
case Result::CmdError:
|
|
|
|
|
return "CMD_ERROR";
|
|
|
|
|
case Result::QueryError:
|
|
|
|
|
return "QUERY_ERROR";
|
|
|
|
|
case Result::ExecError:
|
|
|
|
|
return "EXEC_ERROR";
|
2022-10-01 17:10:44 +02:00
|
|
|
case Result::False:
|
|
|
|
|
return "FALSE";
|
|
|
|
|
case Result::True:
|
|
|
|
|
return "TRUE";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SCPI::input(QString line)
|
|
|
|
|
{
|
2024-04-07 14:11:04 +02:00
|
|
|
cmdQueue.append(line);
|
|
|
|
|
process();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SCPI::process()
|
|
|
|
|
{
|
|
|
|
|
while(!WAIexecuting && !cmdQueue.isEmpty()) {
|
|
|
|
|
auto cmd = cmdQueue.front();
|
|
|
|
|
cmdQueue.pop_front();
|
|
|
|
|
auto cmds = cmd.split(";");
|
|
|
|
|
SCPINode *lastNode = this;
|
|
|
|
|
for(auto cmd : cmds) {
|
|
|
|
|
if(cmd.size() > 0) {
|
|
|
|
|
if(cmd[0] == ':' || cmd[0] == '*') {
|
|
|
|
|
// reset to root node
|
|
|
|
|
lastNode = this;
|
|
|
|
|
}
|
|
|
|
|
if(cmd[0] == ':') {
|
|
|
|
|
cmd.remove(0, 1);
|
|
|
|
|
}
|
|
|
|
|
auto response = lastNode->parse(cmd, lastNode);
|
2024-04-07 14:22:57 +02:00
|
|
|
if(response == getResultName(Result::Error)) {
|
|
|
|
|
setFlag(Flag::CME);
|
|
|
|
|
} else if(response == getResultName(Result::QueryError)) {
|
2024-04-12 12:23:54 +02:00
|
|
|
setFlag(Flag::CME);
|
|
|
|
|
} else if(response == getResultName(Result::CmdError)) {
|
|
|
|
|
setFlag(Flag::CME);
|
2024-04-07 14:22:57 +02:00
|
|
|
} else if(response == getResultName(Result::ExecError)) {
|
|
|
|
|
setFlag(Flag::EXE);
|
|
|
|
|
} else if(response == getResultName(Result::Empty)) {
|
|
|
|
|
// do nothing
|
|
|
|
|
} else {
|
|
|
|
|
emit output(response);
|
|
|
|
|
}
|
2024-04-07 12:54:42 +02:00
|
|
|
}
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SCPI::someOperationCompleted()
|
|
|
|
|
{
|
|
|
|
|
if(!isOperationPending()) {
|
|
|
|
|
// all operations are complete
|
|
|
|
|
if(OCAS) {
|
|
|
|
|
OCAS = false;
|
2024-04-12 12:23:54 +02:00
|
|
|
if(OPCsetBitScheduled) {
|
|
|
|
|
setFlag(Flag::OPC);
|
|
|
|
|
OPCsetBitScheduled = false;
|
|
|
|
|
}
|
2024-04-07 14:11:04 +02:00
|
|
|
if(OPCQueryScheduled) {
|
|
|
|
|
output("1");
|
|
|
|
|
OPCQueryScheduled = false;
|
2024-04-07 12:54:42 +02:00
|
|
|
}
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
if(WAIexecuting) {
|
|
|
|
|
WAIexecuting = false;
|
|
|
|
|
// process any queued commands
|
|
|
|
|
process();
|
2022-10-01 17:10:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-07 14:11:04 +02:00
|
|
|
void SCPI::setFlag(Flag flag)
|
|
|
|
|
{
|
2024-04-07 14:39:27 +02:00
|
|
|
SESR |= ((int) flag);
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SCPI::clearFlag(Flag flag)
|
|
|
|
|
{
|
2024-04-07 14:39:27 +02:00
|
|
|
SESR &= ~((int) flag);
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPI::getFlag(Flag flag)
|
|
|
|
|
{
|
2024-04-07 14:39:27 +02:00
|
|
|
return SESR & (int) flag;
|
2024-04-07 14:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
2022-10-01 17:10:44 +02:00
|
|
|
SCPINode::~SCPINode()
|
|
|
|
|
{
|
|
|
|
|
if(parent) {
|
|
|
|
|
parent->remove(this);
|
|
|
|
|
}
|
|
|
|
|
while(commands.size() > 0) {
|
|
|
|
|
delete commands.front();
|
|
|
|
|
commands.erase(commands.begin());
|
|
|
|
|
}
|
|
|
|
|
while(subnodes.size() > 0) {
|
|
|
|
|
auto node = subnodes.front();
|
|
|
|
|
remove(node);
|
|
|
|
|
delete node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPINode::add(SCPINode *node)
|
|
|
|
|
{
|
|
|
|
|
if(nameCollision(node->name)) {
|
|
|
|
|
qWarning() << "Unable to add SCPI node, name collision: " << node->name;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
subnodes.push_back(node);
|
|
|
|
|
node->parent = this;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPINode::remove(SCPINode *node)
|
|
|
|
|
{
|
|
|
|
|
auto it = std::find(subnodes.begin(), subnodes.end(), node);
|
|
|
|
|
if(it != subnodes.end()) {
|
|
|
|
|
subnodes.erase(it);
|
|
|
|
|
node->parent = nullptr;
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPINode::add(SCPICommand *cmd)
|
|
|
|
|
{
|
|
|
|
|
if(nameCollision(cmd->name())) {
|
|
|
|
|
qWarning() << "Unable to add SCPI node, name collision: " << cmd->name();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
commands.push_back(cmd);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 22:42:33 +01:00
|
|
|
bool SCPINode::addDoubleParameter(QString name, double ¶m, bool gettable, bool settable, std::function<void(void)> setCallback)
|
2022-12-12 17:39:17 +01:00
|
|
|
{
|
2022-12-12 22:42:33 +01:00
|
|
|
auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString {
|
2022-12-12 17:39:17 +01:00
|
|
|
if(SCPI::paramToDouble(params, 0, param)) {
|
2022-12-12 22:42:33 +01:00
|
|
|
if(setCallback) {
|
|
|
|
|
setCallback();
|
|
|
|
|
}
|
2022-12-12 17:39:17 +01:00
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
} else {
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
}
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
2022-12-12 22:42:33 +01:00
|
|
|
auto query = gettable ? [=](QStringList params) -> QString {
|
2022-12-12 17:39:17 +01:00
|
|
|
Q_UNUSED(params)
|
|
|
|
|
return QString::number(param);
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
|
|
|
|
return add(new SCPICommand(name, cmd, query));
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 22:42:33 +01:00
|
|
|
bool SCPINode::addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable, bool settable, std::function<void(void)> setCallback)
|
2022-12-12 17:39:17 +01:00
|
|
|
{
|
2022-12-12 22:42:33 +01:00
|
|
|
auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString {
|
2022-12-12 17:39:17 +01:00
|
|
|
unsigned long long value;
|
|
|
|
|
if(SCPI::paramToULongLong(params, 0, value)) {
|
|
|
|
|
param = value;
|
2022-12-12 22:42:33 +01:00
|
|
|
if(setCallback) {
|
|
|
|
|
setCallback();
|
|
|
|
|
}
|
2022-12-12 17:39:17 +01:00
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
} else {
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
}
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
2022-12-12 22:42:33 +01:00
|
|
|
auto query = gettable ? [=](QStringList params) -> QString {
|
2022-12-12 17:39:17 +01:00
|
|
|
Q_UNUSED(params)
|
|
|
|
|
return QString::number(param);
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
|
|
|
|
return add(new SCPICommand(name, cmd, query));
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 22:42:33 +01:00
|
|
|
bool SCPINode::addBoolParameter(QString name, bool ¶m, bool gettable, bool settable, std::function<void(void)> setCallback)
|
|
|
|
|
{
|
|
|
|
|
auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString {
|
|
|
|
|
if(SCPI::paramToBool(params, 0, param)) {
|
|
|
|
|
if(setCallback) {
|
|
|
|
|
setCallback();
|
|
|
|
|
}
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Empty);
|
|
|
|
|
} else {
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
}
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
|
|
|
|
auto query = gettable ? [=](QStringList params) -> QString {
|
|
|
|
|
Q_UNUSED(params)
|
|
|
|
|
return param ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
|
|
|
|
} : (std::function<QString(QStringList)>) nullptr;
|
|
|
|
|
return add(new SCPICommand(name, cmd, query));
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 17:39:17 +01:00
|
|
|
bool SCPINode::changeName(QString newname)
|
|
|
|
|
{
|
|
|
|
|
if(newname == name) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if(parent) {
|
|
|
|
|
if(parent->nameCollision(newname)) {
|
|
|
|
|
// new name would result in a collision
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
name = newname;
|
2022-12-12 22:42:33 +01:00
|
|
|
return true;
|
2022-12-12 17:39:17 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-07 14:11:04 +02:00
|
|
|
void SCPINode::setOperationPending(bool pending)
|
|
|
|
|
{
|
|
|
|
|
if(operationPending != pending) {
|
|
|
|
|
operationPending = pending;
|
|
|
|
|
if(!operationPending) {
|
|
|
|
|
// operation completed, needs to perform check if all operations are complete
|
|
|
|
|
auto root = this;
|
|
|
|
|
while(root->parent) {
|
|
|
|
|
root = root->parent;
|
|
|
|
|
}
|
|
|
|
|
auto scpi = static_cast<SCPI*>(root);
|
|
|
|
|
scpi->someOperationCompleted();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SCPINode::isOperationPending()
|
|
|
|
|
{
|
|
|
|
|
if(operationPending) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
for(auto node : subnodes) {
|
|
|
|
|
if(node->isOperationPending()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// no node has any pending operations
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-01 17:10:44 +02:00
|
|
|
bool SCPINode::nameCollision(QString name)
|
|
|
|
|
{
|
|
|
|
|
for(auto n : subnodes) {
|
|
|
|
|
if(SCPI::match(n->name, name)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(auto c : commands) {
|
|
|
|
|
if(SCPI::match(c->name(), name)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SCPINode::createCommandList(QString prefix, QString &list)
|
|
|
|
|
{
|
|
|
|
|
for(auto c : commands) {
|
|
|
|
|
if(c->queryable()) {
|
|
|
|
|
list += prefix + c->name() + "?\n";
|
|
|
|
|
}
|
|
|
|
|
if(c->executable()) {
|
|
|
|
|
list += prefix + c->name() + '\n';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(auto n : subnodes) {
|
|
|
|
|
n->createCommandList(prefix + n->name + ":", list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SCPINode::parse(QString cmd, SCPINode* &lastNode)
|
|
|
|
|
{
|
|
|
|
|
if(cmd.isEmpty()) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
auto splitPos = cmd.indexOf(':');
|
|
|
|
|
if(splitPos > 0) {
|
|
|
|
|
// have not reached a leaf, find next subnode
|
|
|
|
|
auto subnode = cmd.left(splitPos);
|
|
|
|
|
for(auto n : subnodes) {
|
2023-07-21 13:43:38 +02:00
|
|
|
if(SCPI::match(n->name, subnode.toUpper())) {
|
2022-10-01 17:10:44 +02:00
|
|
|
// pass on to next level
|
|
|
|
|
return n->parse(cmd.right(cmd.size() - splitPos - 1), lastNode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// unable to find subnode
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
} else {
|
|
|
|
|
// no more levels, search for command
|
|
|
|
|
auto params = cmd.split(" ");
|
|
|
|
|
auto cmd = params.front();
|
|
|
|
|
params.pop_front();
|
|
|
|
|
bool isQuery = false;
|
|
|
|
|
if (cmd[cmd.size()-1]=='?') {
|
|
|
|
|
isQuery = true;
|
|
|
|
|
cmd.chop(1);
|
|
|
|
|
}
|
|
|
|
|
for(auto c : commands) {
|
2023-07-21 13:43:38 +02:00
|
|
|
if(SCPI::match(c->name(), cmd.toUpper())) {
|
2022-10-01 17:10:44 +02:00
|
|
|
// save current node in case of non-root for the next command
|
|
|
|
|
lastNode = this;
|
2023-07-21 13:43:38 +02:00
|
|
|
if(c->convertToUppercase()) {
|
|
|
|
|
for(auto &p : params) {
|
|
|
|
|
p = p.toUpper();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-01 17:10:44 +02:00
|
|
|
if(isQuery) {
|
|
|
|
|
return c->query(params);
|
|
|
|
|
} else {
|
|
|
|
|
return c->execute(params);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// couldn't find command
|
|
|
|
|
return SCPI::getResultName(SCPI::Result::Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SCPICommand::execute(QStringList params)
|
|
|
|
|
{
|
|
|
|
|
if(fn_cmd == nullptr) {
|
2024-04-07 14:22:57 +02:00
|
|
|
return SCPI::getResultName(SCPI::Result::CmdError);
|
2022-10-01 17:10:44 +02:00
|
|
|
} else {
|
2024-04-07 14:22:57 +02:00
|
|
|
auto ret = fn_cmd(params);
|
|
|
|
|
if(ret == SCPI::getResultName(SCPI::Result::Error)) {
|
|
|
|
|
ret = SCPI::getResultName(SCPI::Result::CmdError);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
2022-10-01 17:10:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SCPICommand::query(QStringList params)
|
|
|
|
|
{
|
|
|
|
|
if(fn_query == nullptr) {
|
2024-04-07 14:22:57 +02:00
|
|
|
return SCPI::getResultName(SCPI::Result::QueryError);
|
2022-10-01 17:10:44 +02:00
|
|
|
} else {
|
2024-04-07 14:22:57 +02:00
|
|
|
auto ret = fn_query(params);
|
|
|
|
|
if(ret == SCPI::getResultName(SCPI::Result::Error)) {
|
|
|
|
|
ret = SCPI::getResultName(SCPI::Result::QueryError);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
2022-10-01 17:10:44 +02:00
|
|
|
}
|
|
|
|
|
}
|