mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-09-10 07:06:34 -04:00
848 lines
26 KiB
C++
848 lines
26 KiB
C++
///////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 2020 Jon Beniston, M7RCE //
|
|
// Copyright (C) 2020 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 <QDebug>
|
|
#include <QTcpServer>
|
|
#include <QTcpSocket>
|
|
#include <QEventLoop>
|
|
#include <QTimer>
|
|
|
|
#include <cmath>
|
|
|
|
#include "SWGDeviceState.h"
|
|
#include "SWGSuccessResponse.h"
|
|
#include "SWGErrorResponse.h"
|
|
#include "SWGDeviceSettings.h"
|
|
#include "SWGChannelSettings.h"
|
|
#include "SWGDeviceSet.h"
|
|
|
|
#include "webapi/webapiadapterinterface.h"
|
|
#include "webapi/webapiutils.h"
|
|
|
|
#include "rigctlserverworker.h"
|
|
|
|
MESSAGE_CLASS_DEFINITION(RigCtlServerWorker::MsgConfigureRigCtlServerWorker, Message)
|
|
|
|
const unsigned int RigCtlServerWorker::m_CmdLength = 1024;
|
|
const unsigned int RigCtlServerWorker::m_ResponseLength = 1024;
|
|
const struct RigCtlServerWorker::ModeDemod RigCtlServerWorker::m_modeMap[] = {
|
|
{"FM", "NFMDemod"},
|
|
{"WFM", "WFMDemod"},
|
|
{"AM", "AMDemod"},
|
|
{"LSB", "SSBDemod"},
|
|
{"USB", "SSBDemod"},
|
|
{nullptr, nullptr}
|
|
};
|
|
|
|
RigCtlServerWorker::RigCtlServerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
|
m_state(idle),
|
|
m_tcpServer(nullptr),
|
|
m_clientConnection(nullptr),
|
|
m_webAPIAdapterInterface(webAPIAdapterInterface),
|
|
m_msgQueueToFeature(nullptr),
|
|
m_running(false),
|
|
m_mutex(QMutex::Recursive)
|
|
{
|
|
qDebug("RigCtlServerWorker::RigCtlServerWorker");
|
|
}
|
|
|
|
RigCtlServerWorker::~RigCtlServerWorker()
|
|
{
|
|
m_inputMessageQueue.clear();
|
|
}
|
|
|
|
void RigCtlServerWorker::reset()
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
m_inputMessageQueue.clear();
|
|
}
|
|
|
|
bool RigCtlServerWorker::startWork()
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
|
m_running = true;
|
|
return m_running;
|
|
}
|
|
|
|
void RigCtlServerWorker::stopWork()
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
|
restartServer(false, 0);
|
|
m_running = false;
|
|
}
|
|
|
|
void RigCtlServerWorker::handleInputMessages()
|
|
{
|
|
Message* message;
|
|
|
|
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
|
{
|
|
if (handleMessage(*message)) {
|
|
delete message;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool RigCtlServerWorker::handleMessage(const Message& cmd)
|
|
{
|
|
if (MsgConfigureRigCtlServerWorker::match(cmd))
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
MsgConfigureRigCtlServerWorker& cfg = (MsgConfigureRigCtlServerWorker&) cmd;
|
|
qDebug() << "RigCtlServerWorker::handleMessage: MsgConfigureRigCtlServerWorker";
|
|
|
|
applySettings(cfg.getSettings(), cfg.getForce());
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void RigCtlServerWorker::applySettings(const RigCtlServerSettings& settings, bool force)
|
|
{
|
|
qDebug() << "RigCtlServerWorker::applySettings:"
|
|
<< " m_title: " << settings.m_title
|
|
<< " m_rgbColor: " << settings.m_rgbColor
|
|
<< " m_enabled: " << settings.m_enabled
|
|
<< " m_deviceIndex: " << settings.m_deviceIndex
|
|
<< " m_channelIndex: " << settings.m_channelIndex
|
|
<< " m_rigCtlPort: " << settings.m_rigCtlPort
|
|
<< " m_maxFrequencyOffset: " << settings.m_maxFrequencyOffset
|
|
<< " force: " << force;
|
|
|
|
if ((settings.m_rigCtlPort != m_settings.m_rigCtlPort) ||
|
|
(settings.m_enabled != m_settings.m_enabled) || force)
|
|
{
|
|
restartServer(settings.m_enabled, settings.m_rigCtlPort);
|
|
}
|
|
|
|
m_settings = settings;
|
|
}
|
|
|
|
void RigCtlServerWorker::restartServer(bool enabled, uint32_t port)
|
|
{
|
|
if (m_tcpServer)
|
|
{
|
|
if (m_clientConnection)
|
|
{
|
|
m_clientConnection->close();
|
|
delete m_clientConnection;
|
|
m_clientConnection = nullptr;
|
|
}
|
|
|
|
disconnect(m_tcpServer, &QTcpServer::newConnection, this, &RigCtlServerWorker::acceptConnection);
|
|
m_tcpServer->close();
|
|
delete m_tcpServer;
|
|
m_tcpServer = nullptr;
|
|
}
|
|
|
|
if (enabled)
|
|
{
|
|
qDebug() << "RigCtlServerWorker::restartServer: server enabled on port " << port;
|
|
m_tcpServer = new QTcpServer(this);
|
|
|
|
if (!m_tcpServer->listen(QHostAddress::Any, port)) {
|
|
qWarning("RigCtrl failed to listen on port %u. Check it is not already in use.", port);
|
|
} else {
|
|
connect(m_tcpServer, &QTcpServer::newConnection, this, &RigCtlServerWorker::acceptConnection);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qDebug() << "RigCtlServerWorker::restartServer: server disabled";
|
|
}
|
|
}
|
|
|
|
void RigCtlServerWorker::acceptConnection()
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
m_clientConnection = m_tcpServer->nextPendingConnection();
|
|
|
|
if (!m_clientConnection) {
|
|
return;
|
|
}
|
|
|
|
connect(m_clientConnection, &QIODevice::readyRead, this, &RigCtlServerWorker::getCommand);
|
|
connect(m_clientConnection, &QAbstractSocket::disconnected, m_clientConnection, &QObject::deleteLater);
|
|
}
|
|
|
|
// Get rigctl command and start processing it
|
|
void RigCtlServerWorker::getCommand()
|
|
{
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
char cmd[m_CmdLength];
|
|
qint64 len;
|
|
rig_errcode_e rigCtlRC;
|
|
char response[m_ResponseLength];
|
|
std::fill(response, response + m_ResponseLength, '\0');
|
|
|
|
// Get rigctld command from client
|
|
len = m_clientConnection->readLine(cmd, sizeof(cmd));
|
|
|
|
if (len != -1)
|
|
{
|
|
//qDebug() << "RigCtrl::getCommand - " << cmd;
|
|
if (!strncmp(cmd, "F ", 2) || !strncmp(cmd, "set_freq ", 9))
|
|
{
|
|
// Set frequency
|
|
double targetFrequency = atof(cmd[0] == 'F' ? &cmd[2] : &cmd[9]);
|
|
setFrequency(targetFrequency, rigCtlRC);
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
else if (!strncmp(cmd, "f", 1) || !strncmp(cmd, "get_freq", 8))
|
|
{
|
|
// Get frequency - need to add centerFrequency and inputFrequencyOffset
|
|
double frequency;
|
|
|
|
if (getFrequency(frequency, rigCtlRC)) {
|
|
sprintf(response, "%u\n", (unsigned int) frequency);
|
|
} else {
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
}
|
|
else if (!strncmp(cmd, "M ?", 3) || !(strncmp(cmd, "set_mode ?", 10)))
|
|
{
|
|
// Return list of modes supported
|
|
char *p = response;
|
|
|
|
for (int i = 0; m_modeMap[i].mode != nullptr; i++) {
|
|
p += sprintf(p, "%s ", m_modeMap[i].mode);
|
|
}
|
|
|
|
p += sprintf(p, "\n");
|
|
}
|
|
else if (!strncmp(cmd, "M ", 2) || !(strncmp(cmd, "set_mode ", 9)))
|
|
{
|
|
// Set mode
|
|
// Map rigctrl mode name to SDRangel modem name
|
|
const char *targetModem = nullptr;
|
|
const char *targetMode = nullptr;
|
|
int targetBW = -1;
|
|
char *p = (cmd[0] == 'M' ? &cmd[2] : &cmd[9]);
|
|
int i, l;
|
|
|
|
for (i = 0; m_modeMap[i].mode != nullptr; i++)
|
|
{
|
|
l = strlen(m_modeMap[i].mode);
|
|
|
|
if (!strncmp(p, m_modeMap[i].mode, l))
|
|
{
|
|
targetMode = m_modeMap[i].mode;
|
|
targetModem = m_modeMap[i].modem;
|
|
p += l;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Save bandwidth, if given
|
|
while(isspace(*p)) {
|
|
p++;
|
|
}
|
|
|
|
if (isdigit(*p))
|
|
{
|
|
targetBW = atoi(p);
|
|
}
|
|
|
|
if (m_modeMap[i].modem != nullptr)
|
|
{
|
|
changeModem(targetMode, targetModem, targetBW, rigCtlRC);
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
else
|
|
{
|
|
sprintf(response, "RPRT %d\n", RIG_EINVAL);
|
|
m_clientConnection->write(response, strlen(response));
|
|
}
|
|
}
|
|
else if (!strncmp(cmd, "m", 1) || !(strncmp(cmd, "get_mode", 8)))
|
|
{
|
|
// Get mode
|
|
const char *mode;
|
|
double passband;
|
|
|
|
if (getMode(&mode, passband, rigCtlRC))
|
|
{
|
|
if (passband < 0) {
|
|
sprintf(response, "%s\n", mode);
|
|
} else {
|
|
sprintf(response, "%s %u\n", mode, (unsigned int) passband);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
}
|
|
else if (!strncmp(cmd, "set_powerstat 0", 15))
|
|
{
|
|
// Power off radio
|
|
setPowerOff(rigCtlRC);
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
else if (!strncmp(cmd, "set_powerstat 1", 15))
|
|
{
|
|
// Power on radio
|
|
setPowerOn(rigCtlRC);
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
else if (!strncmp(cmd, "get_powerstat", 13))
|
|
{
|
|
// Return if powered on or off
|
|
bool power;
|
|
if (getPower(power, rigCtlRC))
|
|
{
|
|
if (power) {
|
|
sprintf(response, "1\n");
|
|
} else {
|
|
sprintf(response, "0\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(response, "RPRT %d\n", rigCtlRC);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Unimplemented command
|
|
sprintf(response, "RPRT %d\n", RIG_ENIMPL);
|
|
m_clientConnection->write(response, strlen(response));
|
|
}
|
|
}
|
|
|
|
m_clientConnection->write(response, strlen(response));
|
|
}
|
|
|
|
bool RigCtlServerWorker::setFrequency(double targetFrequency, rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
int httpRC;
|
|
|
|
// Get current device center frequency
|
|
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(
|
|
m_settings.m_deviceIndex,
|
|
deviceSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: get device frequency error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
|
|
double freq;
|
|
|
|
if (WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", freq))
|
|
{
|
|
bool outOfRange = std::abs(freq - targetFrequency) > m_settings.m_maxFrequencyOffset;
|
|
|
|
if (outOfRange)
|
|
{
|
|
// Update centerFrequency
|
|
WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", targetFrequency);
|
|
QStringList deviceSettingsKeys;
|
|
deviceSettingsKeys.append("centerFrequency");
|
|
deviceSettingsResponse.init();
|
|
deviceSettingsResponse.fromJsonObject(*jsonObj);
|
|
SWGSDRangel::SWGErrorResponse errorResponse2;
|
|
|
|
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch(
|
|
m_settings.m_deviceIndex,
|
|
false, // PATCH
|
|
deviceSettingsKeys,
|
|
deviceSettingsResponse,
|
|
errorResponse2
|
|
);
|
|
|
|
if (httpRC/100 == 2)
|
|
{
|
|
qDebug("RigCtlServerWorker::setFrequency: set device frequency %f OK", targetFrequency);
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: set device frequency error %d: %s",
|
|
httpRC, qPrintable(*errorResponse2.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Update inputFrequencyOffset (offet if in range else zero)
|
|
float targetOffset = outOfRange ? 0 : targetFrequency - freq;
|
|
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
|
// Get channel settings containing inputFrequencyOffset, so we can patch it
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
|
m_settings.m_deviceIndex,
|
|
m_settings.m_channelIndex,
|
|
channelSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: get channel offset frequency error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
jsonObj = channelSettingsResponse.asJsonObject();
|
|
|
|
if (WebAPIUtils::setSubObjectDouble(*jsonObj, "inputFrequencyOffset", targetOffset))
|
|
{
|
|
QStringList channelSettingsKeys;
|
|
channelSettingsKeys.append("inputFrequencyOffset");
|
|
channelSettingsResponse.init();
|
|
channelSettingsResponse.fromJsonObject(*jsonObj);
|
|
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
|
m_settings.m_deviceIndex,
|
|
m_settings.m_channelIndex,
|
|
false, // PATCH
|
|
channelSettingsKeys,
|
|
channelSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 == 2)
|
|
{
|
|
qDebug("RigCtlServerWorker::setFrequency: set channel offset frequency %f OK", targetOffset);
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: set channel frequency offset error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: No inputFrequencyOffset key in channel settings");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: no centerFrequency key in device settings");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
rigCtlRC = RIG_OK; // return OK
|
|
return true;
|
|
}
|
|
|
|
bool RigCtlServerWorker::getFrequency(double& frequency, rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
int httpRC;
|
|
|
|
// Get current device center frequency
|
|
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(
|
|
m_settings.m_deviceIndex,
|
|
deviceSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::getFrequency: get device frequency error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
|
|
double deviceFreq;
|
|
|
|
if (WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", deviceFreq))
|
|
{
|
|
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
|
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
|
m_settings.m_deviceIndex,
|
|
m_settings.m_channelIndex,
|
|
channelSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: get channel offset frequency error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
QJsonObject *jsonObj2 = channelSettingsResponse.asJsonObject();
|
|
double channelOffset;
|
|
|
|
if (WebAPIUtils::getSubObjectDouble(*jsonObj2, "inputFrequencyOffset", channelOffset))
|
|
{
|
|
frequency = deviceFreq + channelOffset;
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: No inputFrequencyOffset key in channel settings");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setFrequency: no centerFrequency key in device settings");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
rigCtlRC = RIG_OK;
|
|
return true;
|
|
}
|
|
|
|
bool RigCtlServerWorker::changeModem(const char *newMode, const char *newModemId, int newModemBw, rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceSet deviceSetResponse;
|
|
SWGSDRangel::SWGSuccessResponse successResponse;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
int httpRC;
|
|
int nbChannels;
|
|
int currentOffset;
|
|
|
|
// get deviceset details to get the number of channel modems
|
|
httpRC = m_webAPIAdapterInterface->devicesetGet(
|
|
m_settings.m_deviceIndex,
|
|
deviceSetResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2) // error
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: deevice set get information error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
if (!WebAPIUtils::getObjectInt(*deviceSetResponse.asJsonObject(), "channelcount", nbChannels))
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: no channelcount key in device set information");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
QList<QJsonObject> channelObjects;
|
|
|
|
if (!WebAPIUtils::getObjectObjects(*deviceSetResponse.asJsonObject(), "channels", channelObjects))
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: no channels key in device set information");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
if (m_settings.m_channelIndex < channelObjects.size())
|
|
{
|
|
const QJsonObject& channelInfo = channelObjects.at(m_settings.m_channelIndex);
|
|
|
|
if (!WebAPIUtils::getObjectInt(channelInfo, "deltaFrequency", currentOffset))
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: no deltaFrequency key in device set channel information");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: channel not found in device set channels information");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
// delete current modem
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelDelete(
|
|
m_settings.m_deviceIndex,
|
|
m_settings.m_channelIndex,
|
|
successResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2) // error
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: delete channel error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
// create new modem
|
|
SWGSDRangel::SWGChannelSettings query;
|
|
QString newModemIdStr(newModemId);
|
|
bool lsb = !strncmp(newMode, "LSB", 3);
|
|
query.init();
|
|
query.setChannelType(new QString(newModemIdStr));
|
|
query.setDirection(0);
|
|
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelPost(
|
|
m_settings.m_deviceIndex,
|
|
query,
|
|
successResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: create channel error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
// wait for channel switchover
|
|
QEventLoop loop;
|
|
QTimer *timer = new QTimer(this);
|
|
connect(timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
|
timer->start(200);
|
|
loop.exec();
|
|
delete timer;
|
|
|
|
// when a new channel is created it is put last in the list
|
|
qDebug("RigCtlServerWorker::changeModem: created %s at %d", newModemId, nbChannels-1);
|
|
|
|
if (m_msgQueueToFeature)
|
|
{
|
|
RigCtlServerSettings::MsgChannelIndexChange *msg = RigCtlServerSettings::MsgChannelIndexChange::create(nbChannels-1);
|
|
m_msgQueueToFeature->push(msg);
|
|
}
|
|
|
|
SWGSDRangel::SWGChannelSettings swgChannelSettings;
|
|
QStringList channelSettingsKeys;
|
|
channelSettingsKeys.append("inputFrequencyOffset");
|
|
QString jsonSettingsStr = tr("\"inputFrequencyOffset\":%1").arg(currentOffset);
|
|
|
|
if (lsb || (newModemBw >= 0))
|
|
{
|
|
int bw = lsb ? (newModemBw < 0 ? -3000 : -newModemBw) : newModemBw;
|
|
channelSettingsKeys.append("rfBandwidth");
|
|
jsonSettingsStr.append(tr(",\"rfBandwidth\":%2").arg(bw));
|
|
}
|
|
|
|
QString jsonStr = tr("{ \"channelType\": \"%1\", \"%2Settings\": {%3}}")
|
|
.arg(QString(newModemId))
|
|
.arg(QString(newModemId))
|
|
.arg(jsonSettingsStr);
|
|
swgChannelSettings.fromJson(jsonStr);
|
|
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
|
m_settings.m_deviceIndex,
|
|
nbChannels-1, // new index
|
|
false, // PATCH
|
|
channelSettingsKeys,
|
|
swgChannelSettings,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::changeModem: set channel settings error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
rigCtlRC = RIG_OK;
|
|
return true;
|
|
}
|
|
|
|
bool RigCtlServerWorker::getMode(const char **mode, double& passband, rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
int httpRC;
|
|
|
|
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
|
m_settings.m_deviceIndex,
|
|
m_settings.m_channelIndex,
|
|
channelSettingsResponse,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::getModem: get channel settings error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
|
QString channelType;
|
|
int i;
|
|
|
|
if (!WebAPIUtils::getObjectString(*jsonObj, "channelType", channelType))
|
|
{
|
|
qWarning("RigCtlServerWorker::getModem: no channelType key in channel settings");
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; m_modeMap[i].mode != nullptr; i++)
|
|
{
|
|
if (!channelType.compare(m_modeMap[i].modem))
|
|
{
|
|
*mode = m_modeMap[i].mode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!m_modeMap[i].mode)
|
|
{
|
|
qWarning("RigCtlServerWorker::getModem: channel type not implemented: %s", qPrintable(channelType));
|
|
rigCtlRC = RIG_ENIMPL;
|
|
return false;
|
|
}
|
|
|
|
|
|
if (WebAPIUtils::getSubObjectDouble(*jsonObj, "rfBandwidth", passband))
|
|
{
|
|
if (!channelType.compare("SSBDemod"))
|
|
{
|
|
if (passband < 0) { // LSB
|
|
passband = -passband;
|
|
} else { // USB
|
|
*mode = m_modeMap[i+1].mode;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
passband = -1;
|
|
}
|
|
|
|
rigCtlRC = RIG_OK;
|
|
return true;
|
|
}
|
|
|
|
bool RigCtlServerWorker::setPowerOn(rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceState response;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
|
|
int httpRC = m_webAPIAdapterInterface->devicesetDeviceRunPost(
|
|
m_settings.m_deviceIndex,
|
|
response,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 == 2)
|
|
{
|
|
qDebug("RigCtlServerWorker::setPowerOn: set device start OK");
|
|
rigCtlRC = RIG_OK;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setPowerOn: set device start error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool RigCtlServerWorker::setPowerOff(rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceState response;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
|
|
int httpRC = m_webAPIAdapterInterface->devicesetDeviceRunDelete(
|
|
m_settings.m_deviceIndex,
|
|
response,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 == 2)
|
|
{
|
|
qDebug("RigCtlServerWorker::setPowerOff: set device stop OK");
|
|
rigCtlRC = RIG_OK;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::setPowerOff: set device stop error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool RigCtlServerWorker::getPower(bool& power, rig_errcode_e& rigCtlRC)
|
|
{
|
|
SWGSDRangel::SWGDeviceState response;
|
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
|
|
|
int httpRC = m_webAPIAdapterInterface->devicesetDeviceRunGet(
|
|
m_settings.m_deviceIndex,
|
|
response,
|
|
errorResponse
|
|
);
|
|
|
|
if (httpRC/100 != 2)
|
|
{
|
|
qWarning("RigCtlServerWorker::getPower: get device run state error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
QJsonObject *jsonObj = response.asJsonObject();
|
|
QString state;
|
|
|
|
if (WebAPIUtils::getObjectString(*jsonObj, "state", state))
|
|
{
|
|
qDebug("RigCtlServerWorker::getPower: run state is %s", qPrintable(state));
|
|
|
|
if (state.compare("running")) {
|
|
power = false; // not equal
|
|
} else {
|
|
power = true; // equal
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qWarning("RigCtlServerWorker::getPower: get device run state error %d: %s",
|
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
|
rigCtlRC = RIG_EINVAL;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|