mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-23 00:18:37 -05:00
Merge pull request #1650 from srcejon/fix_1641
Rotator Controller Updates
This commit is contained in:
commit
e376dd0454
@ -62,7 +62,3 @@ if (WIN32)
|
||||
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
|
||||
endif()
|
||||
|
||||
# Install debug symbols
|
||||
if (WIN32)
|
||||
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
|
||||
endif()
|
||||
|
@ -203,12 +203,11 @@ void APRS::applySettings(const APRSSettings& settings, const QList<QString>& set
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
APRSWorker::MsgConfigureAPRSWorker *msg = APRSWorker::MsgConfigureAPRSWorker::create(
|
||||
settings, settingsKeys, force
|
||||
);
|
||||
|
||||
if (m_worker) {
|
||||
if (m_worker)
|
||||
{
|
||||
APRSWorker::MsgConfigureAPRSWorker *msg = APRSWorker::MsgConfigureAPRSWorker::create(
|
||||
settings, settingsKeys, force
|
||||
);
|
||||
m_worker->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,11 @@ set(gs232controller_SOURCES
|
||||
gs232controllerplugin.cpp
|
||||
gs232controllerworker.cpp
|
||||
gs232controllerwebapiadapter.cpp
|
||||
controllerprotocol.cpp
|
||||
gs232protocol.cpp
|
||||
spidprotocol.cpp
|
||||
rotctrldprotocol.cpp
|
||||
dfmprotocol.cpp
|
||||
)
|
||||
|
||||
set(gs232controller_HEADERS
|
||||
@ -15,6 +20,11 @@ set(gs232controller_HEADERS
|
||||
gs232controllerreport.h
|
||||
gs232controllerworker.h
|
||||
gs232controllerwebapiadapter.h
|
||||
controllerprotocol.h
|
||||
gs232protocol.h
|
||||
spidprotocol.h
|
||||
rotctrldprotocol.h
|
||||
dfmprotocol.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
@ -26,10 +36,13 @@ if(NOT SERVER_MODE)
|
||||
${gs232controller_SOURCES}
|
||||
gs232controllergui.cpp
|
||||
gs232controllergui.ui
|
||||
dfmstatusdialog.cpp
|
||||
dfmstatusdialog.ui
|
||||
)
|
||||
set(gs232controller_HEADERS
|
||||
${gs232controller_HEADERS}
|
||||
gs232controllergui.h
|
||||
dfmstatusdialog.h
|
||||
)
|
||||
|
||||
set(TARGET_NAME featuregs232controller)
|
||||
|
157
plugins/feature/gs232controller/controllerprotocol.cpp
Normal file
157
plugins/feature/gs232controller/controllerprotocol.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 <QRegularExpression>
|
||||
|
||||
#include "maincore.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
|
||||
#include "gs232controllerreport.h"
|
||||
#include "controllerprotocol.h"
|
||||
#include "gs232protocol.h"
|
||||
#include "spidprotocol.h"
|
||||
#include "rotctrldprotocol.h"
|
||||
#include "dfmprotocol.h"
|
||||
|
||||
ControllerProtocol::ControllerProtocol() :
|
||||
m_device(nullptr),
|
||||
m_lastAzimuth(-1.0f),
|
||||
m_lastElevation(-1.0f),
|
||||
m_msgQueueToFeature(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ControllerProtocol::~ControllerProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void ControllerProtocol::setAzimuth(float azimuth)
|
||||
{
|
||||
setAzimuthElevation(azimuth, m_lastElevation);
|
||||
m_lastAzimuth = azimuth;
|
||||
}
|
||||
|
||||
void ControllerProtocol::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
m_lastAzimuth = azimuth;
|
||||
m_lastElevation = elevation;
|
||||
}
|
||||
|
||||
void ControllerProtocol::applySettings(const GS232ControllerSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||
{
|
||||
if (force) {
|
||||
m_settings = settings;
|
||||
} else {
|
||||
m_settings.applySettings(settingsKeys, settings);
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerProtocol::sendMessage(Message *message)
|
||||
{
|
||||
m_msgQueueToFeature->push(message);
|
||||
}
|
||||
|
||||
void ControllerProtocol::reportAzEl(float az, float el)
|
||||
{
|
||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az, el));
|
||||
}
|
||||
|
||||
void ControllerProtocol::reportError(const QString &message)
|
||||
{
|
||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(message));
|
||||
}
|
||||
|
||||
void ControllerProtocol::getPosition(float& latitude, float& longitude)
|
||||
{
|
||||
if (!m_settings.m_track)
|
||||
{
|
||||
// When not tracking, use My Position from preferences
|
||||
// although this precludes having different antennas at different positions
|
||||
latitude = MainCore::instance()->getSettings().getLatitude();
|
||||
longitude = MainCore::instance()->getSettings().getLongitude();
|
||||
}
|
||||
else
|
||||
{
|
||||
// When tracking, get position from Star Tracker / Sat Tracker
|
||||
QRegularExpression re("([FTR])(\\d+):(\\d+)");
|
||||
QRegularExpressionMatch match = re.match(m_settings.m_source);
|
||||
if (match.hasMatch())
|
||||
{
|
||||
QString kind = match.captured(1);
|
||||
int setIndex = match.captured(2).toInt();
|
||||
int index = match.captured(3).toInt();
|
||||
if (kind == 'F')
|
||||
{
|
||||
double lat, lon;
|
||||
bool latOk = ChannelWebAPIUtils::getFeatureSetting(setIndex, index, "latitude", lat);
|
||||
bool lonOk = ChannelWebAPIUtils::getFeatureSetting(setIndex, index, "longitude", lon);
|
||||
if (latOk && lonOk)
|
||||
{
|
||||
latitude = (float)lat;
|
||||
longitude = (float)lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ControllerProtocol::getPosition - Failed to get position from source: " << m_settings.m_source;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double lat, lon;
|
||||
bool latOk = ChannelWebAPIUtils::getChannelSetting(setIndex, index, "latitude", lat);
|
||||
bool lonOk = ChannelWebAPIUtils::getChannelSetting(setIndex, index, "longitude", lon);
|
||||
if (latOk && lonOk)
|
||||
{
|
||||
latitude = (float)lat;
|
||||
longitude = (float)lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ControllerProtocol::getPosition - Failed to get position from source: " << m_settings.m_source;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ControllerProtocol::getPosition - Couldn't parse source: " << m_settings.m_source;
|
||||
}
|
||||
}
|
||||
//qDebug() << "ControllerProtocol::getPosition: " << latitude << longitude;
|
||||
}
|
||||
|
||||
ControllerProtocol *ControllerProtocol::create(GS232ControllerSettings::Protocol protocol)
|
||||
{
|
||||
switch (protocol)
|
||||
{
|
||||
case GS232ControllerSettings::GS232:
|
||||
return new GS232Protocol();
|
||||
break;
|
||||
case GS232ControllerSettings::SPID:
|
||||
return new SPIDProtocol();
|
||||
break;
|
||||
case GS232ControllerSettings::ROTCTLD:
|
||||
return new RotCtrlDProtocol();
|
||||
break;
|
||||
case GS232ControllerSettings::DFM:
|
||||
return new DFMProtocol();
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
57
plugins/feature/gs232controller/controllerprotocol.h
Normal file
57
plugins/feature/gs232controller/controllerprotocol.h
Normal file
@ -0,0 +1,57 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_FEATURE_CONTROLLERPROTOCOL_H_
|
||||
#define INCLUDE_FEATURE_CONTROLLERPROTOCOL_H_
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
#include "util/messagequeue.h"
|
||||
#include "gs232controllersettings.h"
|
||||
#include "gs232controller.h"
|
||||
|
||||
class ControllerProtocol
|
||||
{
|
||||
public:
|
||||
ControllerProtocol();
|
||||
virtual ~ControllerProtocol();
|
||||
virtual void setAzimuth(float azimuth);
|
||||
virtual void setAzimuthElevation(float azimuth, float elevation) = 0;
|
||||
virtual void readData() = 0;
|
||||
virtual void update() = 0;
|
||||
void setDevice(QIODevice *device) { m_device = device; }
|
||||
virtual void applySettings(const GS232ControllerSettings& settings, const QList<QString>& settingsKeys, bool force);
|
||||
void setMessageQueue(MessageQueue *messageQueue) { m_msgQueueToFeature = messageQueue; }
|
||||
void sendMessage(Message *message);
|
||||
void reportAzEl(float az, float el);
|
||||
void reportError(const QString &message);
|
||||
void getPosition(float& latitude, float& longitude);
|
||||
|
||||
static ControllerProtocol *create(GS232ControllerSettings::Protocol protocol);
|
||||
|
||||
protected:
|
||||
QIODevice *m_device;
|
||||
GS232ControllerSettings m_settings;
|
||||
float m_lastAzimuth;
|
||||
float m_lastElevation;
|
||||
|
||||
private:
|
||||
MessageQueue *m_msgQueueToFeature;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_CONTROLLERPROTOCOL_H_
|
||||
|
239
plugins/feature/gs232controller/dfmprotocol.cpp
Normal file
239
plugins/feature/gs232controller/dfmprotocol.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 "util/astronomy.h"
|
||||
|
||||
#include "dfmprotocol.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(DFMProtocol::MsgReportDFMStatus, Message)
|
||||
|
||||
DFMProtocol::DFMProtocol() :
|
||||
m_packetCnt(0)
|
||||
{
|
||||
// Call periodicTask() every 500ms
|
||||
connect(&m_timer, &QTimer::timeout, this, &DFMProtocol::periodicTask);
|
||||
m_timer.start(500);
|
||||
}
|
||||
|
||||
DFMProtocol::~DFMProtocol()
|
||||
{
|
||||
m_timer.stop();
|
||||
}
|
||||
|
||||
void DFMProtocol::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
// This gets position from source plugin in track is enabled (E.g. Star Tracker / Satellite tracker)
|
||||
// or My Position preference, if not tracking
|
||||
float latitude, longitude;
|
||||
getPosition(latitude, longitude);
|
||||
|
||||
// Convert az/el to RA/Dec
|
||||
AzAlt aa;
|
||||
aa.az = azimuth;
|
||||
aa.alt = elevation;
|
||||
QDateTime dt = QDateTime::currentDateTime();
|
||||
RADec rd = Astronomy::azAltToRaDec(aa, latitude, longitude, dt);
|
||||
// Save as target
|
||||
m_targetRA = rd.ra;
|
||||
m_targetDec = rd.dec;
|
||||
|
||||
// Call parent method to save m_lastAzimuth and m_lastElevation
|
||||
ControllerProtocol::setAzimuthElevation(azimuth, elevation);
|
||||
}
|
||||
|
||||
// Handle data received from LCU
|
||||
// Packets are of the form #L,L,f,f,..,f;
|
||||
void DFMProtocol::readData()
|
||||
{
|
||||
char c;
|
||||
while (m_device->getChar(&c))
|
||||
{
|
||||
if (c == '#')
|
||||
{
|
||||
// Start packet
|
||||
m_rxBuffer = QString(c);
|
||||
}
|
||||
else if (c == ';')
|
||||
{
|
||||
// End packet
|
||||
m_rxBuffer.append(c);
|
||||
|
||||
// Only process if we have valid packet
|
||||
if (m_rxBuffer.startsWith('#'))
|
||||
{
|
||||
parseLCUResponse(m_rxBuffer);
|
||||
m_rxBuffer = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "DFMProtocol::readData - Ignoring partial packet: " << m_rxBuffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rxBuffer.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DFMProtocol::parseLCUResponse(const QString& packet)
|
||||
{
|
||||
qDebug() << "DFMProtocol::parseLCUResponse - " << packet;
|
||||
|
||||
// Check packet starts with expected header
|
||||
if (!packet.startsWith("#L,L,"))
|
||||
{
|
||||
qDebug() << "DFMProtocol::readData - Ignoring non LCU packet: " << m_rxBuffer;
|
||||
return;
|
||||
}
|
||||
|
||||
// Strip off header and footer
|
||||
QString strippedPacket = packet.mid(5, packet.length() - 6);
|
||||
|
||||
// Convert packet to list of strings
|
||||
QStringList dataStrings = strippedPacket.split(",");
|
||||
|
||||
// Extract values we are interested in
|
||||
DFMStatus status;
|
||||
|
||||
int statl = (int)dataStrings[1].toFloat();
|
||||
status.m_initialized = statl & 1;
|
||||
status.m_brakesOn = (statl >> 1) & 1;
|
||||
status.m_trackOn = (statl >> 2) & 1;
|
||||
status.m_slewEnabled = (statl >> 3) & 1;
|
||||
status.m_lubePumpsOn = (statl >> 4) & 1;
|
||||
status.m_approachingSWLimit = (statl >> 5) & 1;
|
||||
status.m_finalSWLimit = (statl >> 6) & 1;
|
||||
status.m_slewing = (statl >> 7) & 1;
|
||||
|
||||
int stath = (int)dataStrings[2].toFloat();
|
||||
status.m_setting = stath & 1;
|
||||
status.m_haltMotorsIn = (stath >> 1) & 1;
|
||||
status.m_excomSwitchOn = (stath >> 2) & 1;
|
||||
status.m_servoPackAlarm = (stath >> 3) & 1;
|
||||
status.m_targetOutOfRange = (stath >> 4) & 1;
|
||||
status.m_cosdecOn = (stath >> 5) & 1;
|
||||
status.m_rateCorrOn = (stath >> 6) & 1;
|
||||
status.m_drivesOn = (stath >> 7) & 1;
|
||||
|
||||
int statlh = (int)dataStrings[3].toFloat();
|
||||
status.m_pumpsReady = statlh & 1;
|
||||
// Bit 1 unknown
|
||||
status.m_minorPlus = (statlh >> 2) & 1;
|
||||
status.m_minorMinus = (statlh >> 3) & 1;
|
||||
status.m_majorPlus = (statlh >> 4) & 1;
|
||||
status.m_majorMinus = (statlh >> 5) & 1;
|
||||
status.m_nextObjectActive = (statlh >> 6) & 1;
|
||||
status.m_auxTrackRate = (statlh >> 7) & 1;
|
||||
|
||||
status.m_siderealTime = dataStrings[5].toFloat();
|
||||
status.m_universalTime = dataStrings[6].toFloat();
|
||||
|
||||
status.m_currentHA = dataStrings[7].toFloat();
|
||||
status.m_currentRA = dataStrings[8].toFloat();
|
||||
status.m_currentDec = dataStrings[9].toFloat();
|
||||
|
||||
status.m_currentX = dataStrings[20].toFloat();
|
||||
status.m_currentY = dataStrings[21].toFloat();
|
||||
|
||||
status.m_siderealRateX = dataStrings[30].toFloat();
|
||||
status.m_siderealRateY = dataStrings[31].toFloat();
|
||||
|
||||
status.m_torqueX = dataStrings[34].toFloat();
|
||||
status.m_torqueY = dataStrings[35].toFloat();
|
||||
|
||||
status.m_controller = (DFMStatus::Controller)dataStrings[38].toInt();
|
||||
|
||||
status.m_rateX = dataStrings[39].toFloat();
|
||||
status.m_rateY = dataStrings[40].toFloat();
|
||||
|
||||
// Display status in GUI
|
||||
sendMessage(MsgReportDFMStatus::create(status));
|
||||
|
||||
// Convert current X/Y to Az/El
|
||||
AzAlt aa = Astronomy::xy85ToAzAlt(status.m_currentX, status.m_currentY);
|
||||
float az = aa.az;
|
||||
float el = aa.alt;
|
||||
reportAzEl(az, el);
|
||||
|
||||
// If this is the second LCU packet, we send a commmand
|
||||
m_packetCnt++;
|
||||
if (m_packetCnt == 2)
|
||||
{
|
||||
m_packetCnt = 0;
|
||||
sendCommand();
|
||||
}
|
||||
}
|
||||
|
||||
void DFMProtocol::sendCommand()
|
||||
{
|
||||
// TODO: Use m_lastAzimuth/m_lastElevation or m_targetRA/m_targetDec to calculate position commands
|
||||
|
||||
// Send a command to the LCU
|
||||
int cmdId = 98;
|
||||
int handPaddle = 0;
|
||||
int frontPanel = (m_settings.m_dfmDrivesOn << 2)
|
||||
| (m_settings.m_dfmTrackOn << 3)
|
||||
| (m_settings.m_dfmLubePumpsOn << 4)
|
||||
| (m_settings.m_dfmBrakesOn << 7);
|
||||
|
||||
QString cmd = QString("#M,R,%1,%2.000000,%3.000000;").arg(cmdId).arg(handPaddle).arg(frontPanel);
|
||||
m_device->write(cmd.toLatin1());
|
||||
|
||||
qDebug() << "DFMProtocol::sendCommand - " << cmd;
|
||||
}
|
||||
|
||||
// Request current Az/El
|
||||
void DFMProtocol::update()
|
||||
{
|
||||
// This is called periodically for protocols that need to send a command to get current az/el
|
||||
// However, for this protocol, we might not need to do anything here,
|
||||
// if we're continually calling reportAzEl() in response to packets received from the LCU.
|
||||
//sendCommand();
|
||||
}
|
||||
|
||||
void DFMProtocol::periodicTask()
|
||||
{
|
||||
// Just as an example, this will be called every 500ms. Can be removed if not needed
|
||||
}
|
||||
|
||||
// This is called when new settings are available from GUI (or API).
|
||||
void DFMProtocol::applySettings(const GS232ControllerSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||
{
|
||||
if (settingsKeys.contains("dfmTrackOn") || force)
|
||||
{
|
||||
// Do something with settings.m_dfmTrackOn if needed
|
||||
}
|
||||
if (settingsKeys.contains("dfmLubePumpsOn") || force)
|
||||
{
|
||||
// Do something with settings.m_dfmLubePumpsOn if needed
|
||||
}
|
||||
if (settingsKeys.contains("dfmBrakesOn") || force)
|
||||
{
|
||||
// Do something with settings.m_dfmBreaksOn if needed
|
||||
}
|
||||
if (settingsKeys.contains("dfmDrivesOn") || force)
|
||||
{
|
||||
// Do something with settings.m_dfmDrivesOn if needed
|
||||
}
|
||||
|
||||
// Call parent method to set m_settings to settings
|
||||
ControllerProtocol::applySettings(settings, settingsKeys, force);
|
||||
}
|
||||
|
120
plugins/feature/gs232controller/dfmprotocol.h
Normal file
120
plugins/feature/gs232controller/dfmprotocol.h
Normal file
@ -0,0 +1,120 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_FEATURE_DFMPROTOCOL_H_
|
||||
#define INCLUDE_FEATURE_DFMPROTOCOL_H_
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "util/message.h"
|
||||
#include "controllerprotocol.h"
|
||||
|
||||
class DFMProtocol : public QObject, public ControllerProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
struct DFMStatus {
|
||||
// STATL
|
||||
bool m_initialized;
|
||||
bool m_brakesOn;
|
||||
bool m_trackOn;
|
||||
bool m_slewEnabled;
|
||||
bool m_lubePumpsOn;
|
||||
bool m_approachingSWLimit;
|
||||
bool m_finalSWLimit;
|
||||
bool m_slewing;
|
||||
// STATH
|
||||
bool m_setting;
|
||||
bool m_haltMotorsIn;
|
||||
bool m_excomSwitchOn;
|
||||
bool m_servoPackAlarm;
|
||||
bool m_targetOutOfRange;
|
||||
bool m_cosdecOn;
|
||||
bool m_rateCorrOn;
|
||||
bool m_drivesOn;
|
||||
// STATLH
|
||||
bool m_pumpsReady;
|
||||
bool m_minorPlus;
|
||||
bool m_minorMinus;
|
||||
bool m_majorPlus;
|
||||
bool m_majorMinus;
|
||||
bool m_nextObjectActive;
|
||||
bool m_auxTrackRate;
|
||||
// Other status information
|
||||
float m_currentHA;
|
||||
float m_currentRA;
|
||||
float m_currentDec;
|
||||
float m_currentX;
|
||||
float m_currentY;
|
||||
enum Controller {NONE, OCU, LCU, MCU} m_controller;
|
||||
float m_torqueX;
|
||||
float m_torqueY;
|
||||
float m_rateX;
|
||||
float m_rateY;
|
||||
float m_siderealRateX;
|
||||
float m_siderealRateY;
|
||||
float m_siderealTime;
|
||||
float m_universalTime;
|
||||
};
|
||||
|
||||
// Message from DFMProtocol to the GUI, with status information to display
|
||||
class MsgReportDFMStatus : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
DFMStatus getDFMStatus() const { return m_dfmStatus; }
|
||||
|
||||
static MsgReportDFMStatus* create(const DFMStatus& dfmStatus)
|
||||
{
|
||||
return new MsgReportDFMStatus(dfmStatus);
|
||||
}
|
||||
private:
|
||||
DFMStatus m_dfmStatus;
|
||||
|
||||
MsgReportDFMStatus(const DFMStatus& dfmStatus) :
|
||||
Message(),
|
||||
m_dfmStatus(dfmStatus)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
DFMProtocol();
|
||||
~DFMProtocol();
|
||||
void setAzimuthElevation(float azimuth, float elevation) override;
|
||||
void readData() override;
|
||||
void update() override;
|
||||
void applySettings(const GS232ControllerSettings& settings, const QList<QString>& settingsKeys, bool force) override;
|
||||
|
||||
private:
|
||||
void parseLCUResponse(const QString& packet);
|
||||
void sendCommand();
|
||||
|
||||
QTimer m_timer;
|
||||
|
||||
QString m_rxBuffer;
|
||||
int m_packetCnt;
|
||||
|
||||
float m_targetRA;
|
||||
float m_targetDec;
|
||||
|
||||
private slots:
|
||||
void periodicTask();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_DFMPROTOCOL_H_
|
||||
|
69
plugins/feature/gs232controller/dfmstatusdialog.cpp
Normal file
69
plugins/feature/gs232controller/dfmstatusdialog.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 "util/units.h"
|
||||
|
||||
#include "dfmstatusdialog.h"
|
||||
|
||||
DFMStatusDialog::DFMStatusDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DFMStatusDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// Make checkboxes read-only
|
||||
ui->trackOn->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
ui->driveOn->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
ui->brakesOn->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
ui->pumpsOn->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
ui->controller->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
void DFMStatusDialog::displayStatus(const DFMProtocol::DFMStatus& dfmStatus)
|
||||
{
|
||||
ui->currentHA->setText(QString::number(dfmStatus.m_currentHA, 'f'));
|
||||
ui->currentRA->setText(QString::number(dfmStatus.m_currentRA, 'f'));
|
||||
ui->currentDec->setText(QString::number(dfmStatus.m_currentDec, 'f'));
|
||||
|
||||
ui->st->setText(Units::decimalHoursToHoursMinutesAndSeconds(dfmStatus.m_siderealTime));
|
||||
ui->ut->setText(Units::decimalHoursToHoursMinutesAndSeconds(dfmStatus.m_universalTime));
|
||||
|
||||
ui->currentX->setText(QString::number(dfmStatus.m_currentX, 'f'));
|
||||
ui->currentY->setText(QString::number(dfmStatus.m_currentY, 'f'));
|
||||
ui->siderealRateX->setText(QString::number(dfmStatus.m_siderealRateX, 'f'));
|
||||
ui->siderealRateY->setText(QString::number(dfmStatus.m_siderealRateY, 'f'));
|
||||
ui->rateX->setText(QString::number(dfmStatus.m_rateX, 'f'));
|
||||
ui->rateY->setText(QString::number(dfmStatus.m_rateY, 'f'));
|
||||
ui->torqueX->setText(QString::number(dfmStatus.m_torqueX, 'f'));
|
||||
ui->torqueY->setText(QString::number(dfmStatus.m_torqueY, 'f'));
|
||||
|
||||
ui->trackOn->setChecked(dfmStatus.m_trackOn);
|
||||
ui->driveOn->setChecked(dfmStatus.m_drivesOn);
|
||||
ui->brakesOn->setChecked(dfmStatus.m_brakesOn);
|
||||
ui->pumpsOn->setChecked(dfmStatus.m_pumpsReady); // ?
|
||||
ui->controller->setCurrentIndex((int)dfmStatus.m_controller);
|
||||
}
|
||||
|
||||
DFMStatusDialog::~DFMStatusDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DFMStatusDialog::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
40
plugins/feature/gs232controller/dfmstatusdialog.h
Normal file
40
plugins/feature/gs232controller/dfmstatusdialog.h
Normal file
@ -0,0 +1,40 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_DFMSTATUSSDIALOG_H
|
||||
#define INCLUDE_DFMSTATUSSDIALOG_H
|
||||
|
||||
#include "ui_dfmstatusdialog.h"
|
||||
#include "dfmprotocol.h"
|
||||
|
||||
class DFMStatusDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DFMStatusDialog(QWidget* parent = 0);
|
||||
~DFMStatusDialog();
|
||||
void displayStatus(const DFMProtocol::DFMStatus& dfmStatus);
|
||||
|
||||
private slots:
|
||||
void accept();
|
||||
|
||||
private:
|
||||
Ui::DFMStatusDialog* ui;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_DFMSTATUSSDIALOG_H
|
||||
|
413
plugins/feature/gs232controller/dfmstatusdialog.ui
Normal file
413
plugins/feature/gs232controller/dfmstatusdialog.ui
Normal file
@ -0,0 +1,413 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DFMStatusDialog</class>
|
||||
<widget class="QDialog" name="DFMStatusDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>474</width>
|
||||
<height>488</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DFM Status</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="statusGroup">
|
||||
<property name="title">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="trackOnLabel">
|
||||
<property name="text">
|
||||
<string>Track</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="trackOn">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="driverOnLabel">
|
||||
<property name="text">
|
||||
<string>Drives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="driveOn">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="brakesOnLabel">
|
||||
<property name="text">
|
||||
<string>Brakes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="brakesOn">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="pumpsOnLabel">
|
||||
<property name="text">
|
||||
<string>Pumps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="pumpsOn">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="controller">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>OCU</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>LCU</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MCU</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="controllerLabel">
|
||||
<property name="text">
|
||||
<string>Controller</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="antennaPositionGroup">
|
||||
<property name="title">
|
||||
<string>Antenna Position</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="currentRA">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="currentRALabel">
|
||||
<property name="text">
|
||||
<string>RA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="currentDecLabel">
|
||||
<property name="text">
|
||||
<string>Dec</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="currentDec">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="currentHALabel">
|
||||
<property name="text">
|
||||
<string>HA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="currentHA">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QGroupBox" name="dateTimeGroup">
|
||||
<property name="title">
|
||||
<string>Date/Time</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="stLabel">
|
||||
<property name="text">
|
||||
<string>ST</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="utLabel">
|
||||
<property name="text">
|
||||
<string>UT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="st">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="ut">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="xyStatus">
|
||||
<property name="title">
|
||||
<string>X/Y Status</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="torqueX">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="currentX">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="torqueXYLabel">
|
||||
<property name="text">
|
||||
<string>Torque</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="rateX">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="torqueY">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="currentY">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="rateXYLabel">
|
||||
<property name="text">
|
||||
<string>Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="xColumnLabel">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="currentXYLabel">
|
||||
<property name="text">
|
||||
<string>Antenna</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="yColumnLabel">
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="rateY">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="siderealRateXYLabel">
|
||||
<property name="text">
|
||||
<string>Sidereal Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="siderealRateX">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLineEdit" name="siderealRateY">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DFMStatusDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DFMStatusDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -39,12 +39,14 @@
|
||||
#include "gs232controller.h"
|
||||
#include "gs232controllerworker.h"
|
||||
#include "gs232controllerreport.h"
|
||||
#include "dfmprotocol.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgConfigureGS232Controller, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgStartStop, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportWorker, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportAvailableChannelOrFeatures, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgScanAvailableChannelOrFeatures, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportSerialPorts, Message)
|
||||
|
||||
const char* const GS232Controller::m_featureIdURI = "sdrangel.feature.gs232controller";
|
||||
const char* const GS232Controller::m_featureId = "GS232Controller";
|
||||
@ -52,7 +54,9 @@ const char* const GS232Controller::m_featureId = "GS232Controller";
|
||||
GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||
Feature(m_featureIdURI, webAPIAdapterInterface),
|
||||
m_thread(nullptr),
|
||||
m_worker(nullptr)
|
||||
m_worker(nullptr),
|
||||
m_currentAzimuth(0.0f),
|
||||
m_currentElevation(0.0f)
|
||||
{
|
||||
qDebug("GS232Controller::GS232Controller: webAPIAdapterInterface: %p", webAPIAdapterInterface);
|
||||
setObjectName(m_featureId);
|
||||
@ -90,10 +94,14 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface)
|
||||
this,
|
||||
&GS232Controller::handleChannelRemoved
|
||||
);
|
||||
connect(&m_timer, &QTimer::timeout, this, &GS232Controller::scanSerialPorts);
|
||||
m_timer.start(5000);
|
||||
}
|
||||
|
||||
GS232Controller::~GS232Controller()
|
||||
{
|
||||
m_timer.stop();
|
||||
disconnect(&m_timer, &QTimer::timeout, this, &GS232Controller::scanSerialPorts);
|
||||
QObject::disconnect(
|
||||
MainCore::instance(),
|
||||
&MainCore::channelRemoved,
|
||||
@ -244,6 +252,16 @@ bool GS232Controller::handleMessage(const Message& cmd)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (DFMProtocol::MsgReportDFMStatus::match(cmd))
|
||||
{
|
||||
// Forward to GUI
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
DFMProtocol::MsgReportDFMStatus& report = (DFMProtocol::MsgReportDFMStatus&) cmd;
|
||||
getMessageQueueToGUI()->push(new DFMProtocol::MsgReportDFMStatus(report));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
@ -256,8 +274,8 @@ bool GS232Controller::getOnTarget() const
|
||||
float targetAziumth, targetElevation;
|
||||
m_settings.calcTargetAzEl(targetAziumth, targetElevation);
|
||||
float readTolerance = m_settings.m_tolerance + 0.0f;
|
||||
bool onTarget = (std::fabs(m_currentAzimuth - targetAziumth) < readTolerance)
|
||||
&& (std::fabs(m_currentElevation - targetElevation) < readTolerance);
|
||||
bool onTarget = (std::fabs(m_currentAzimuth - targetAziumth) <= readTolerance)
|
||||
&& (std::fabs(m_currentElevation - targetElevation) <= readTolerance);
|
||||
return onTarget;
|
||||
}
|
||||
|
||||
@ -471,6 +489,8 @@ void GS232Controller::webapiFormatFeatureSettings(
|
||||
response.getGs232ControllerSettings()->setElevationMax(settings.m_elevationMax);
|
||||
response.getGs232ControllerSettings()->setTolerance(settings.m_tolerance);
|
||||
response.getGs232ControllerSettings()->setProtocol(settings.m_protocol);
|
||||
response.getGs232ControllerSettings()->setPrecision(settings.m_precision);
|
||||
response.getGs232ControllerSettings()->setCoordinates((int)settings.m_coordinates);
|
||||
|
||||
if (response.getGs232ControllerSettings()->getTitle()) {
|
||||
*response.getGs232ControllerSettings()->getTitle() = settings.m_title;
|
||||
@ -559,6 +579,12 @@ void GS232Controller::webapiUpdateFeatureSettings(
|
||||
if (featureSettingsKeys.contains("protocol")) {
|
||||
settings.m_protocol = (GS232ControllerSettings::Protocol)response.getGs232ControllerSettings()->getProtocol();
|
||||
}
|
||||
if (featureSettingsKeys.contains("precision")) {
|
||||
settings.m_precision = response.getGs232ControllerSettings()->getPrecision();
|
||||
}
|
||||
if (featureSettingsKeys.contains("coordinates")) {
|
||||
settings.m_coordinates = (GS232ControllerSettings::Coordinates)response.getGs232ControllerSettings()->getCoordinates();
|
||||
}
|
||||
if (featureSettingsKeys.contains("title")) {
|
||||
settings.m_title = *response.getGs232ControllerSettings()->getTitle();
|
||||
}
|
||||
@ -644,6 +670,12 @@ void GS232Controller::webapiReverseSendSettings(const QList<QString>& featureSet
|
||||
if (featureSettingsKeys.contains("protocol") || force) {
|
||||
swgGS232ControllerSettings->setProtocol((int)settings.m_protocol);
|
||||
}
|
||||
if (featureSettingsKeys.contains("precision") || force) {
|
||||
swgGS232ControllerSettings->setPrecision(settings.m_precision);
|
||||
}
|
||||
if (featureSettingsKeys.contains("coordinates") || force) {
|
||||
swgGS232ControllerSettings->setCoordinates(settings.m_coordinates);
|
||||
}
|
||||
if (featureSettingsKeys.contains("title") || force) {
|
||||
swgGS232ControllerSettings->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
@ -686,14 +718,9 @@ void GS232Controller::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& r
|
||||
response.getGs232ControllerReport()->getSources()->append(new QString(itemText));
|
||||
}
|
||||
|
||||
QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts();
|
||||
QListIterator<QSerialPortInfo> i(serialPorts);
|
||||
response.getGs232ControllerReport()->setSerialPorts(new QList<QString*>());
|
||||
|
||||
while (i.hasNext())
|
||||
{
|
||||
QSerialPortInfo info = i.next();
|
||||
response.getGs232ControllerReport()->getSerialPorts()->append(new QString(info.portName()));
|
||||
for (const auto& serialPort : m_serialPorts) {
|
||||
response.getGs232ControllerReport()->getSerialPorts()->append(new QString(serialPort));
|
||||
}
|
||||
|
||||
float azimuth, elevation;
|
||||
@ -895,3 +922,27 @@ void GS232Controller::handlePipeMessageQueue(MessageQueue* messageQueue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GS232Controller::scanSerialPorts()
|
||||
{
|
||||
// This can take 4ms on Windows, so we don't want to have it in webapiFormatFeatureReport
|
||||
// as polling of target az/el by other plugins will be slowed down
|
||||
QList<QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts();
|
||||
QListIterator<QSerialPortInfo> i(serialPortInfos);
|
||||
QStringList serialPorts;
|
||||
while (i.hasNext())
|
||||
{
|
||||
QSerialPortInfo info = i.next();
|
||||
serialPorts.append(info.portName());
|
||||
}
|
||||
if (m_serialPorts != serialPorts)
|
||||
{
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportSerialPorts *msg = MsgReportSerialPorts::create(serialPorts);
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
}
|
||||
m_serialPorts = serialPorts;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QThread>
|
||||
#include <QNetworkRequest>
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
|
||||
#include "feature/feature.h"
|
||||
#include "util/message.h"
|
||||
@ -138,6 +139,25 @@ public:
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgReportSerialPorts : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const QStringList& getSerialPorts() const { return m_serialPorts; }
|
||||
|
||||
static MsgReportSerialPorts* create(QStringList serialPorts) {
|
||||
return new MsgReportSerialPorts(serialPorts);
|
||||
}
|
||||
|
||||
private:
|
||||
QStringList m_serialPorts;
|
||||
|
||||
MsgReportSerialPorts(QStringList serialPorts) :
|
||||
Message(),
|
||||
m_serialPorts(serialPorts)
|
||||
{}
|
||||
};
|
||||
|
||||
GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface);
|
||||
virtual ~GS232Controller();
|
||||
virtual void destroy() { delete this; }
|
||||
@ -194,6 +214,9 @@ private:
|
||||
QHash<QObject*, GS232ControllerSettings::AvailableChannelOrFeature> m_availableChannelOrFeatures;
|
||||
QObject *m_selectedPipe;
|
||||
|
||||
QTimer m_timer;
|
||||
QStringList m_serialPorts;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
@ -217,6 +240,7 @@ private slots:
|
||||
void handleChannelRemoved(int deviceSetIndex, ChannelAPI *feature);
|
||||
void handleMessagePipeToBeDeleted(int reason, QObject* object);
|
||||
void handlePipeMessageQueue(MessageQueue* messageQueue);
|
||||
void scanSerialPorts();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GS232CONTROLLER_H_
|
||||
|
@ -27,11 +27,13 @@
|
||||
#include "gui/dialogpositioner.h"
|
||||
#include "mainwindow.h"
|
||||
#include "device/deviceuiset.h"
|
||||
#include "util/astronomy.h"
|
||||
|
||||
#include "ui_gs232controllergui.h"
|
||||
#include "gs232controller.h"
|
||||
#include "gs232controllergui.h"
|
||||
#include "gs232controllerreport.h"
|
||||
#include "dfmprotocol.h"
|
||||
|
||||
GS232ControllerGUI* GS232ControllerGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature)
|
||||
{
|
||||
@ -72,6 +74,57 @@ bool GS232ControllerGUI::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::azElToDisplay(float az, float el, float& coord1, float& coord2) const
|
||||
{
|
||||
AzAlt aa;
|
||||
double c1, c2;
|
||||
if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_85)
|
||||
{
|
||||
aa.az = az;
|
||||
aa.alt = el;
|
||||
Astronomy::azAltToXY85(aa, c1, c2);
|
||||
coord1 = (float)c1;
|
||||
coord2 = (float)c2;
|
||||
}
|
||||
else if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_30)
|
||||
{
|
||||
aa.az = az;
|
||||
aa.alt = el;
|
||||
Astronomy::azAltToXY30(aa, c1, c2);
|
||||
coord1 = (float)c1;
|
||||
coord2 = (float)c2;
|
||||
}
|
||||
else
|
||||
{
|
||||
coord1 = az;
|
||||
coord2 = el;
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::displayToAzEl(float coord1, float coord2)
|
||||
{
|
||||
if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_85)
|
||||
{
|
||||
AzAlt aa = Astronomy::xy85ToAzAlt(coord1, coord2);
|
||||
m_settings.m_azimuth = aa.az;
|
||||
m_settings.m_elevation = aa.alt;
|
||||
}
|
||||
else if (m_settings.m_coordinates == GS232ControllerSettings::X_Y_30)
|
||||
{
|
||||
AzAlt aa = Astronomy::xy30ToAzAlt(coord1, coord2);
|
||||
m_settings.m_azimuth = aa.az;
|
||||
m_settings.m_elevation = aa.alt;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.m_azimuth = coord1;
|
||||
m_settings.m_elevation = coord2;
|
||||
}
|
||||
m_settingsKeys.append("azimuth");
|
||||
m_settingsKeys.append("elevation");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
bool GS232ControllerGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (GS232Controller::MsgConfigureGS232Controller::match(message))
|
||||
@ -101,20 +154,35 @@ bool GS232ControllerGUI::handleMessage(const Message& message)
|
||||
else if (GS232ControllerReport::MsgReportAzAl::match(message))
|
||||
{
|
||||
GS232ControllerReport::MsgReportAzAl& azAl = (GS232ControllerReport::MsgReportAzAl&) message;
|
||||
ui->azimuthCurrentText->setText(QString("%1").arg(azAl.getAzimuth()));
|
||||
ui->elevationCurrentText->setText(QString("%1").arg(azAl.getElevation()));
|
||||
float coord1, coord2;
|
||||
azElToDisplay(azAl.getAzimuth(), azAl.getElevation(), coord1, coord2);
|
||||
ui->coord1CurrentText->setText(QString::number(coord1, 'f', m_settings.m_precision));
|
||||
ui->coord2CurrentText->setText(QString::number(coord2, 'f', m_settings.m_precision));
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgTargetAzimuthElevation::match(message))
|
||||
{
|
||||
MainCore::MsgTargetAzimuthElevation& msg = (MainCore::MsgTargetAzimuthElevation&) message;
|
||||
SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = msg.getSWGTargetAzimuthElevation();
|
||||
|
||||
ui->azimuth->setValue(swgTarget->getAzimuth());
|
||||
ui->elevation->setValue(swgTarget->getElevation());
|
||||
float coord1, coord2;
|
||||
azElToDisplay(swgTarget->getAzimuth(), swgTarget->getElevation(), coord1, coord2);
|
||||
ui->coord1->setValue(coord1);
|
||||
ui->coord2->setValue(coord2);
|
||||
ui->targetName->setText(*swgTarget->getName());
|
||||
return true;
|
||||
}
|
||||
else if (GS232Controller::MsgReportSerialPorts::match(message))
|
||||
{
|
||||
GS232Controller::MsgReportSerialPorts& msg = (GS232Controller::MsgReportSerialPorts&) message;
|
||||
updateSerialPortList(msg.getSerialPorts());
|
||||
return true;
|
||||
}
|
||||
else if (DFMProtocol::MsgReportDFMStatus::match(message))
|
||||
{
|
||||
DFMProtocol::MsgReportDFMStatus& report = (DFMProtocol::MsgReportDFMStatus&) message;
|
||||
m_dfmStatusDialog.displayStatus(report.getDFMStatus());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -147,7 +215,8 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
||||
m_featureUISet(featureUISet),
|
||||
m_doApplySettings(true),
|
||||
m_lastFeatureState(0),
|
||||
m_lastOnTarget(false)
|
||||
m_lastOnTarget(false),
|
||||
m_dfmStatusDialog()
|
||||
{
|
||||
m_feature = feature;
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
@ -166,8 +235,9 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(250);
|
||||
|
||||
ui->azimuthCurrentText->setText("-");
|
||||
ui->elevationCurrentText->setText("-");
|
||||
ui->coord1CurrentText->setText("-");
|
||||
ui->coord2CurrentText->setText("-");
|
||||
setProtocol(m_settings.m_protocol); // Hide DFM buttons
|
||||
|
||||
updateSerialPortList();
|
||||
if (ui->serialPort->currentIndex() >= 0) {
|
||||
@ -182,10 +252,13 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
||||
|
||||
// Get pre-existing pipes
|
||||
m_gs232Controller->getInputMessageQueue()->push(GS232Controller::MsgScanAvailableChannelOrFeatures::create());
|
||||
|
||||
new DialogPositioner(&m_dfmStatusDialog, true);
|
||||
}
|
||||
|
||||
GS232ControllerGUI::~GS232ControllerGUI()
|
||||
{
|
||||
m_dfmStatusDialog.close();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -206,11 +279,14 @@ void GS232ControllerGUI::displaySettings()
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_settings.m_title);
|
||||
blockApplySettings(true);
|
||||
ui->azimuth->setValue(m_settings.m_azimuth);
|
||||
ui->elevation->setValue(m_settings.m_elevation);
|
||||
ui->precision->setValue(m_settings.m_precision); // Must set before protocol and az/el
|
||||
ui->protocol->setCurrentIndex((int)m_settings.m_protocol);
|
||||
ui->coordinates->setCurrentIndex((int)m_settings.m_coordinates);
|
||||
float coord1, coord2;
|
||||
azElToDisplay(m_settings.m_azimuth, m_settings.m_elevation, coord1, coord2);
|
||||
ui->coord1->setValue(coord1);
|
||||
ui->coord2->setValue(coord2);
|
||||
ui->connection->setCurrentIndex((int)m_settings.m_connection);
|
||||
updateDecimals(m_settings.m_protocol);
|
||||
if (m_settings.m_serialPort.length() > 0) {
|
||||
ui->serialPort->lineEdit()->setText(m_settings.m_serialPort);
|
||||
}
|
||||
@ -226,6 +302,10 @@ void GS232ControllerGUI::displaySettings()
|
||||
ui->elevationMin->setValue(m_settings.m_elevationMin);
|
||||
ui->elevationMax->setValue(m_settings.m_elevationMax);
|
||||
ui->tolerance->setValue(m_settings.m_tolerance);
|
||||
ui->dfmTrack->setChecked(m_settings.m_dfmTrackOn);
|
||||
ui->dfmLubePumps->setChecked(m_settings.m_dfmLubePumpsOn);
|
||||
ui->dfmBrakes->setChecked(m_settings.m_dfmBrakesOn);
|
||||
ui->dfmDrives->setChecked(m_settings.m_dfmDrivesOn);
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
updateConnectionWidgets();
|
||||
blockApplySettings(false);
|
||||
@ -256,6 +336,19 @@ void GS232ControllerGUI::updateSerialPortList()
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updateSerialPortList(const QStringList& serialPorts)
|
||||
{
|
||||
ui->serialPort->blockSignals(true);
|
||||
ui->serialPort->clear();
|
||||
for (const auto& serialPort : serialPorts) {
|
||||
ui->serialPort->addItem(serialPort);
|
||||
}
|
||||
if (!m_settings.m_serialPort.isEmpty()) {
|
||||
ui->serialPort->setCurrentText(m_settings.m_serialPort);
|
||||
}
|
||||
ui->serialPort->blockSignals(false);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updatePipeList(const QList<GS232ControllerSettings::AvailableChannelOrFeature>& sources)
|
||||
{
|
||||
QString currentText = ui->sources->currentText();
|
||||
@ -359,24 +452,53 @@ void GS232ControllerGUI::on_startStop_toggled(bool checked)
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updateDecimals(GS232ControllerSettings::Protocol protocol)
|
||||
void GS232ControllerGUI::setProtocol(GS232ControllerSettings::Protocol protocol)
|
||||
{
|
||||
if (protocol == GS232ControllerSettings::GS232)
|
||||
{
|
||||
ui->azimuth->setDecimals(0);
|
||||
ui->elevation->setDecimals(0);
|
||||
ui->precision->setValue(0);
|
||||
ui->precision->setEnabled(false);
|
||||
ui->precisionLabel->setEnabled(false);
|
||||
}
|
||||
else if (protocol == GS232ControllerSettings::SPID)
|
||||
{
|
||||
ui->precision->setValue(1);
|
||||
ui->precision->setEnabled(false);
|
||||
ui->precisionLabel->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->azimuth->setDecimals(1);
|
||||
ui->elevation->setDecimals(1);
|
||||
ui->precision->setEnabled(true);
|
||||
ui->precisionLabel->setEnabled(true);
|
||||
}
|
||||
bool dfm = protocol == GS232ControllerSettings::DFM;
|
||||
ui->dfmLine->setVisible(dfm);
|
||||
ui->dfmTrack->setVisible(dfm);
|
||||
ui->dfmLubePumps->setVisible(dfm);
|
||||
ui->dfmBrakes->setVisible(dfm);
|
||||
ui->dfmDrives->setVisible(dfm);
|
||||
ui->dfmShowStatus->setVisible(dfm);
|
||||
|
||||
// See RemoteControlGUI::createGUI() for additional weirdness in trying
|
||||
// to resize a window after widgets are changed
|
||||
getRollupContents()->arrangeRollups();
|
||||
layout()->activate(); // Recalculate sizeHint
|
||||
setMinimumSize(sizeHint());
|
||||
setMaximumSize(sizeHint());
|
||||
resize(sizeHint());
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::setPrecision()
|
||||
{
|
||||
ui->coord1->setDecimals(m_settings.m_precision);
|
||||
ui->coord2->setDecimals(m_settings.m_precision);
|
||||
ui->tolerance->setDecimals(m_settings.m_precision);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_protocol_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_protocol = (GS232ControllerSettings::Protocol)index;
|
||||
updateDecimals(m_settings.m_protocol);
|
||||
setProtocol(m_settings.m_protocol);
|
||||
m_settingsKeys.append("protocol");
|
||||
applySettings();
|
||||
}
|
||||
@ -419,20 +541,16 @@ void GS232ControllerGUI::on_port_valueChanged(int value)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_azimuth_valueChanged(double value)
|
||||
void GS232ControllerGUI::on_coord1_valueChanged(double value)
|
||||
{
|
||||
m_settings.m_azimuth = (float)value;
|
||||
displayToAzEl(value, ui->coord2->value());
|
||||
ui->targetName->setText("");
|
||||
m_settingsKeys.append("azimuth");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_elevation_valueChanged(double value)
|
||||
void GS232ControllerGUI::on_coord2_valueChanged(double value)
|
||||
{
|
||||
m_settings.m_elevation = (float)value;
|
||||
displayToAzEl(ui->coord1->value(), value);
|
||||
ui->targetName->setText("");
|
||||
m_settingsKeys.append("elevation");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_azimuthOffset_valueChanged(int value)
|
||||
@ -484,6 +602,63 @@ void GS232ControllerGUI::on_tolerance_valueChanged(double value)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_precision_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_precision = value;
|
||||
setPrecision();
|
||||
m_settingsKeys.append("precision");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_coordinates_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_coordinates = (GS232ControllerSettings::Coordinates)index;
|
||||
m_settingsKeys.append("coordinates");
|
||||
applySettings();
|
||||
|
||||
float coord1, coord2;
|
||||
azElToDisplay(m_settings.m_azimuth, m_settings.m_elevation, coord1, coord2);
|
||||
|
||||
ui->coord1->blockSignals(true);
|
||||
if (m_settings.m_coordinates == GS232ControllerSettings::AZ_EL)
|
||||
{
|
||||
ui->coord1->setMinimum(0.0);
|
||||
ui->coord1->setMaximum(450.0);
|
||||
ui->coord1->setToolTip("Target azimuth in degrees");
|
||||
ui->coord1Label->setText("Azimuth");
|
||||
ui->coord1CurrentText->setToolTip("Current azimuth in degrees");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->coord1->setMinimum(-90.0);
|
||||
ui->coord1->setMaximum(90.0);
|
||||
ui->coord1->setToolTip("Target X in degrees");
|
||||
ui->coord1Label->setText("X");
|
||||
ui->coord1CurrentText->setToolTip("Current X coordinate in degrees");
|
||||
}
|
||||
ui->coord1->setValue(coord1);
|
||||
ui->coord1->blockSignals(false);
|
||||
ui->coord2->blockSignals(true);
|
||||
if (m_settings.m_coordinates == GS232ControllerSettings::AZ_EL)
|
||||
{
|
||||
ui->coord2->setMinimum(0.0);
|
||||
ui->coord2->setMaximum(180.0);
|
||||
ui->coord2->setToolTip("Target elevation in degrees");
|
||||
ui->coord2Label->setText("Elevation");
|
||||
ui->coord2CurrentText->setToolTip("Current elevation in degrees");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->coord2->setMinimum(-90.0);
|
||||
ui->coord2->setMaximum(90.0);
|
||||
ui->coord2->setToolTip("Target Y in degrees");
|
||||
ui->coord2Label->setText("Y");
|
||||
ui->coord2CurrentText->setToolTip("Current Y coordinate in degrees");
|
||||
}
|
||||
ui->coord2->setValue(coord2);
|
||||
ui->coord2->blockSignals(false);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_track_stateChanged(int state)
|
||||
{
|
||||
m_settings.m_track = state == Qt::Checked;
|
||||
@ -507,6 +682,41 @@ void GS232ControllerGUI::on_sources_currentTextChanged(const QString& text)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_dfmTrack_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_dfmTrackOn = checked;
|
||||
m_settingsKeys.append("dfmTrackOn");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_dfmLubePumps_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_dfmLubePumpsOn = checked;
|
||||
m_settingsKeys.append("dfmLubePumpsOn");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_dfmBrakes_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_dfmBrakesOn = checked;
|
||||
m_settingsKeys.append("dfmBrakesOn");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_dfmDrives_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_dfmDrivesOn = checked;
|
||||
m_settingsKeys.append("dfmDrivesOn");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_dfmShowStatus_clicked()
|
||||
{
|
||||
m_dfmStatusDialog.show();
|
||||
m_dfmStatusDialog.raise();
|
||||
m_dfmStatusDialog.activateWindow();
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updateStatus()
|
||||
{
|
||||
int state = m_gs232Controller->getState();
|
||||
@ -583,8 +793,8 @@ void GS232ControllerGUI::makeUIConnections()
|
||||
QObject::connect(ui->port, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_port_valueChanged);
|
||||
QObject::connect(ui->baudRate, qOverload<int>(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_baudRate_currentIndexChanged);
|
||||
QObject::connect(ui->track, &QCheckBox::stateChanged, this, &GS232ControllerGUI::on_track_stateChanged);
|
||||
QObject::connect(ui->azimuth, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuth_valueChanged);
|
||||
QObject::connect(ui->elevation, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevation_valueChanged);
|
||||
QObject::connect(ui->coord1, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_coord1_valueChanged);
|
||||
QObject::connect(ui->coord2, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_coord2_valueChanged);
|
||||
QObject::connect(ui->sources, &QComboBox::currentTextChanged, this, &GS232ControllerGUI::on_sources_currentTextChanged);
|
||||
QObject::connect(ui->azimuthOffset, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_azimuthOffset_valueChanged);
|
||||
QObject::connect(ui->elevationOffset, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationOffset_valueChanged);
|
||||
@ -593,4 +803,12 @@ void GS232ControllerGUI::makeUIConnections()
|
||||
QObject::connect(ui->elevationMin, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationMin_valueChanged);
|
||||
QObject::connect(ui->elevationMax, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_elevationMax_valueChanged);
|
||||
QObject::connect(ui->tolerance, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_tolerance_valueChanged);
|
||||
QObject::connect(ui->precision, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_precision_valueChanged);
|
||||
QObject::connect(ui->coordinates, qOverload<int>(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_coordinates_currentIndexChanged);
|
||||
QObject::connect(ui->dfmTrack, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmTrack_clicked);
|
||||
QObject::connect(ui->dfmLubePumps, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmLubePumps_clicked);
|
||||
QObject::connect(ui->dfmBrakes, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmBrakes_clicked);
|
||||
QObject::connect(ui->dfmDrives, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmDrives_clicked);
|
||||
QObject::connect(ui->dfmShowStatus, &QToolButton::clicked, this, &GS232ControllerGUI::on_dfmShowStatus_clicked);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "settings/rollupstate.h"
|
||||
|
||||
#include "gs232controllersettings.h"
|
||||
#include "dfmstatusdialog.h"
|
||||
|
||||
class PluginAPI;
|
||||
class FeatureUISet;
|
||||
@ -65,18 +66,24 @@ private:
|
||||
int m_lastFeatureState;
|
||||
bool m_lastOnTarget;
|
||||
|
||||
DFMStatusDialog m_dfmStatusDialog;
|
||||
|
||||
explicit GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
|
||||
virtual ~GS232ControllerGUI();
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void setProtocol(GS232ControllerSettings::Protocol protocol);
|
||||
void setPrecision();
|
||||
void updateConnectionWidgets();
|
||||
void updateDecimals(GS232ControllerSettings::Protocol protocol);
|
||||
void updatePipeList(const QList<GS232ControllerSettings::AvailableChannelOrFeature>& sources);
|
||||
void updateSerialPortList();
|
||||
void updateSerialPortList(const QStringList& serialPorts);
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void azElToDisplay(float az, float el, float& coord1, float& coord2) const;
|
||||
void displayToAzEl(float coord1, float coord2);
|
||||
|
||||
private slots:
|
||||
void onMenuDialogCalled(const QPoint &p);
|
||||
@ -90,8 +97,8 @@ private slots:
|
||||
void on_port_valueChanged(int value);
|
||||
void on_baudRate_currentIndexChanged(int index);
|
||||
void on_track_stateChanged(int state);
|
||||
void on_azimuth_valueChanged(double value);
|
||||
void on_elevation_valueChanged(double value);
|
||||
void on_coord1_valueChanged(double value);
|
||||
void on_coord2_valueChanged(double value);
|
||||
void on_sources_currentTextChanged(const QString& text);
|
||||
void on_azimuthOffset_valueChanged(int value);
|
||||
void on_elevationOffset_valueChanged(int value);
|
||||
@ -100,7 +107,15 @@ private slots:
|
||||
void on_elevationMin_valueChanged(int value);
|
||||
void on_elevationMax_valueChanged(int value);
|
||||
void on_tolerance_valueChanged(double value);
|
||||
void on_precision_valueChanged(int value);
|
||||
void on_coordinates_currentIndexChanged(int index);
|
||||
void on_dfmTrack_clicked(bool checked=false);
|
||||
void on_dfmLubePumps_clicked(bool checked=false);
|
||||
void on_dfmBrakes_clicked(bool checked=false);
|
||||
void on_dfmDrives_clicked(bool checked=false);
|
||||
void on_dfmShowStatus_clicked();
|
||||
void updateStatus();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GS232CONTROLLERGUI_H_
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>360</width>
|
||||
<height>281</height>
|
||||
<height>378</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -43,7 +43,7 @@
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>341</width>
|
||||
<height>81</height>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -96,19 +96,28 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="azimuthtLabel">
|
||||
<widget class="QLabel" name="coord1Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>54</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Azimuth</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="azimuth">
|
||||
<widget class="QDoubleSpinBox" name="coord1">
|
||||
<property name="toolTip">
|
||||
<string>Target azimuth in degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>450.000000000000000</double>
|
||||
@ -119,10 +128,10 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="azimuthCurrentText">
|
||||
<widget class="QLabel" name="coord1CurrentText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -130,7 +139,7 @@
|
||||
<string>Current azimuth in degrees</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>360.0</string>
|
||||
<string>360.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -142,19 +151,28 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="elevationLabel">
|
||||
<widget class="QLabel" name="coord2Label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>54</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Elevation</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="elevation">
|
||||
<widget class="QDoubleSpinBox" name="coord2">
|
||||
<property name="toolTip">
|
||||
<string>Target elevation in degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
@ -165,10 +183,10 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="elevationCurrentText">
|
||||
<widget class="QLabel" name="coord2CurrentText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -176,7 +194,7 @@
|
||||
<string>Current elevation in degrees</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>180.0</string>
|
||||
<string>180.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -219,15 +237,76 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="dfmLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="dfmLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="dfmTrack">
|
||||
<property name="text">
|
||||
<string>Track</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="dfmLubePumps">
|
||||
<property name="text">
|
||||
<string>Pumps</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="dfmBrakes">
|
||||
<property name="text">
|
||||
<string>Brakes</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="dfmDrives">
|
||||
<property name="text">
|
||||
<string>Drives</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="dfmShowStatus">
|
||||
<property name="toolTip">
|
||||
<string>Show the DFM status dialog</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="settingsContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>110</y>
|
||||
<y>140</y>
|
||||
<width>341</width>
|
||||
<height>161</height>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -258,31 +337,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="azimuthMinLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth min</string>
|
||||
<item row="6" column="3">
|
||||
<widget class="QSpinBox" name="precision">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Precision (number of decimal places) of azimuth, elevation and tolerance values</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="azimuthMin">
|
||||
<property name="maximum">
|
||||
<number>450</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="protocolLabel">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="elevationMaxLabel">
|
||||
<property name="text">
|
||||
<string>Elevation max</string>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="host">
|
||||
<property name="toolTip">
|
||||
<string>Hostname / IP address of computer to connect to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -293,6 +367,43 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="toleranceLabel">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="serialPort">
|
||||
<property name="toolTip">
|
||||
<string>Name of serial port to use to connect to the rotator</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="azimuthOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-360</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>360</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="azimuthMaxLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="connectionLabel">
|
||||
<property name="text">
|
||||
@ -300,34 +411,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="elevationMin">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="portLabel">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolerance">
|
||||
<item row="2" column="3">
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="toolTip">
|
||||
<string>Tolerance in degrees</string>
|
||||
<string>TCP port number to connect to</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="serialPortLabel">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="baudRateLabel">
|
||||
<property name="text">
|
||||
<string>Serial Port</string>
|
||||
<string>Baud rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -348,17 +445,48 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="toleranceLabel">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="serialPortLabel">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
<string>Serial Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="elevationOffsetLabel">
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolerance">
|
||||
<property name="toolTip">
|
||||
<string>Tolerance in degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="azimuthMin">
|
||||
<property name="maximum">
|
||||
<number>450</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Elevation offset</string>
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="portLabel">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="elevationMaxLabel">
|
||||
<property name="text">
|
||||
<string>Elevation max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -369,70 +497,29 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QSpinBox" name="elevationOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-180</number>
|
||||
</property>
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="elevationMax">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="host">
|
||||
<property name="toolTip">
|
||||
<string>Hostname / IP address of computer to connect to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="serialPort">
|
||||
<property name="toolTip">
|
||||
<string>Name of serial port to use to connect to the rotator</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<property name="toolTip">
|
||||
<string>Command protocol</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GS-232</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SPID</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>rotctld</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="azimuthMinLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
<string>Azimuth min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="elevationMax">
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="elevationOffsetLabel">
|
||||
<property name="text">
|
||||
<string>Elevation offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="elevationMin">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
@ -498,40 +585,92 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="azimuthMaxLabel">
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="precisionLabel">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Azimuth max</string>
|
||||
<string>Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="azimuthOffset">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
||||
<string>Command protocol</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GS-232</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SPID</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>rotctld</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DFM</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QSpinBox" name="elevationOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-360</number>
|
||||
<number>-180</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>360</number>
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="toolTip">
|
||||
<string>TCP port number to connect to</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="baudRateLabel">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="protocolLabel">
|
||||
<property name="text">
|
||||
<string>Baud rate</string>
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="coordinates">
|
||||
<property name="toolTip">
|
||||
<string>Coordinate system</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Az/El</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>X/Y 85'</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>X/Y 30'</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Coordinates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -541,24 +680,38 @@
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>startStop</tabstop>
|
||||
<tabstop>azimuth</tabstop>
|
||||
<tabstop>elevation</tabstop>
|
||||
<tabstop>coord1</tabstop>
|
||||
<tabstop>coord2</tabstop>
|
||||
<tabstop>track</tabstop>
|
||||
<tabstop>sources</tabstop>
|
||||
<tabstop>targetName</tabstop>
|
||||
<tabstop>protocol</tabstop>
|
||||
<tabstop>connection</tabstop>
|
||||
<tabstop>serialPort</tabstop>
|
||||
<tabstop>baudRate</tabstop>
|
||||
<tabstop>host</tabstop>
|
||||
<tabstop>port</tabstop>
|
||||
<tabstop>azimuthOffset</tabstop>
|
||||
<tabstop>elevationOffset</tabstop>
|
||||
<tabstop>azimuthMin</tabstop>
|
||||
<tabstop>azimuthMax</tabstop>
|
||||
<tabstop>elevationMin</tabstop>
|
||||
<tabstop>elevationMax</tabstop>
|
||||
<tabstop>tolerance</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||
|
@ -49,15 +49,10 @@ void GS232ControllerSettings::resetToDefaults()
|
||||
m_elevation = 0.0f;
|
||||
m_serialPort = "";
|
||||
m_baudRate = 9600;
|
||||
m_host = "127.0.0.1";
|
||||
m_port = 4533;
|
||||
m_track = false;
|
||||
m_source = "";
|
||||
m_title = "Rotator Controller";
|
||||
m_rgbColor = QColor(225, 25, 99).rgb();
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIFeatureSetIndex = 0;
|
||||
m_reverseAPIFeatureIndex = 0;
|
||||
m_azimuthOffset = 0;
|
||||
m_elevationOffset = 0;
|
||||
m_azimuthMin = 0;
|
||||
@ -67,8 +62,19 @@ void GS232ControllerSettings::resetToDefaults()
|
||||
m_tolerance = 1.0f;
|
||||
m_protocol = GS232;
|
||||
m_connection = SERIAL;
|
||||
m_host = "127.0.0.1";
|
||||
m_port = 4533;
|
||||
m_precision = 0;
|
||||
m_coordinates = AZ_EL;
|
||||
m_dfmTrackOn = false;
|
||||
m_dfmLubePumpsOn = false;
|
||||
m_dfmBrakesOn = false;
|
||||
m_dfmDrivesOn = false;
|
||||
m_title = "Rotator Controller";
|
||||
m_rgbColor = QColor(225, 25, 99).rgb();
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIFeatureSetIndex = 0;
|
||||
m_reverseAPIFeatureIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
}
|
||||
|
||||
@ -107,6 +113,12 @@ QByteArray GS232ControllerSettings::serialize() const
|
||||
|
||||
s.writeS32(27, m_workspaceIndex);
|
||||
s.writeBlob(28, m_geometryBytes);
|
||||
s.writeS32(29, m_precision);
|
||||
s.writeS32(30, (int)m_coordinates);
|
||||
s.writeBool(31, m_dfmTrackOn);
|
||||
s.writeBool(32, m_dfmLubePumpsOn);
|
||||
s.writeBool(33, m_dfmBrakesOn);
|
||||
s.writeBool(34, m_dfmDrivesOn);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -169,6 +181,12 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
|
||||
|
||||
d.readS32(27, &m_workspaceIndex, 0);
|
||||
d.readBlob(28, &m_geometryBytes);
|
||||
d.readS32(29, &m_precision, 0);
|
||||
d.readS32(30, (int *)&m_coordinates, (int)AZ_EL);
|
||||
d.readBool(31, &m_dfmTrackOn);
|
||||
d.readBool(32, &m_dfmLubePumpsOn);
|
||||
d.readBool(33, &m_dfmBrakesOn);
|
||||
d.readBool(34, &m_dfmDrivesOn);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -208,33 +226,18 @@ void GS232ControllerSettings::applySettings(const QStringList& settingsKeys, con
|
||||
if (settingsKeys.contains("baudRate")) {
|
||||
m_baudRate = settings.m_baudRate;
|
||||
}
|
||||
if (settingsKeys.contains("host")) {
|
||||
m_host = settings.m_host;
|
||||
}
|
||||
if (settingsKeys.contains("port")) {
|
||||
m_port = settings.m_port;
|
||||
}
|
||||
if (settingsKeys.contains("track")) {
|
||||
m_track = settings.m_track;
|
||||
}
|
||||
if (settingsKeys.contains("source")) {
|
||||
m_source = settings.m_source;
|
||||
}
|
||||
if (settingsKeys.contains("title")) {
|
||||
m_title = settings.m_title;
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor")) {
|
||||
m_rgbColor = settings.m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI")) {
|
||||
m_useReverseAPI = settings.m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIAddress")) {
|
||||
m_reverseAPIAddress = settings.m_reverseAPIAddress;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort")) {
|
||||
m_reverseAPIPort = settings.m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureSetIndex")) {
|
||||
m_reverseAPIFeatureSetIndex = settings.m_reverseAPIFeatureSetIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex")) {
|
||||
m_reverseAPIFeatureIndex = settings.m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("azimuthOffset")) {
|
||||
m_azimuthOffset = settings.m_azimuthOffset;
|
||||
}
|
||||
@ -262,11 +265,44 @@ void GS232ControllerSettings::applySettings(const QStringList& settingsKeys, con
|
||||
if (settingsKeys.contains("connection")) {
|
||||
m_connection = settings.m_connection;
|
||||
}
|
||||
if (settingsKeys.contains("host")) {
|
||||
m_host = settings.m_host;
|
||||
if (settingsKeys.contains("precision")) {
|
||||
m_precision = settings.m_precision;
|
||||
}
|
||||
if (settingsKeys.contains("port")) {
|
||||
m_port = settings.m_port;
|
||||
if (settingsKeys.contains("coordinates")) {
|
||||
m_coordinates = settings.m_coordinates;
|
||||
}
|
||||
if (settingsKeys.contains("dfmTrackOn")) {
|
||||
m_dfmTrackOn = settings.m_dfmTrackOn;
|
||||
}
|
||||
if (settingsKeys.contains("dfmLubePumpsOn")) {
|
||||
m_dfmLubePumpsOn = settings.m_dfmLubePumpsOn;
|
||||
}
|
||||
if (settingsKeys.contains("dfmBrakesOn")) {
|
||||
m_dfmBrakesOn = settings.m_dfmBrakesOn;
|
||||
}
|
||||
if (settingsKeys.contains("dfmDrivesOn")) {
|
||||
m_dfmDrivesOn = settings.m_dfmDrivesOn;
|
||||
}
|
||||
if (settingsKeys.contains("title")) {
|
||||
m_title = settings.m_title;
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor")) {
|
||||
m_rgbColor = settings.m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI")) {
|
||||
m_useReverseAPI = settings.m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIAddress")) {
|
||||
m_reverseAPIAddress = settings.m_reverseAPIAddress;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort")) {
|
||||
m_reverseAPIPort = settings.m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureSetIndex")) {
|
||||
m_reverseAPIFeatureSetIndex = settings.m_reverseAPIFeatureSetIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex")) {
|
||||
m_reverseAPIFeatureIndex = settings.m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("workspaceIndex")) {
|
||||
m_workspaceIndex = settings.m_workspaceIndex;
|
||||
@ -289,33 +325,18 @@ QString GS232ControllerSettings::getDebugString(const QStringList& settingsKeys,
|
||||
if (settingsKeys.contains("baudRate") || force) {
|
||||
ostr << " m_baudRate: " << m_baudRate;
|
||||
}
|
||||
if (settingsKeys.contains("host") || force) {
|
||||
ostr << " m_host: " << m_host.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("port") || force) {
|
||||
ostr << " m_port: " << m_port;
|
||||
}
|
||||
if (settingsKeys.contains("track") || force) {
|
||||
ostr << " m_track: " << m_track;
|
||||
}
|
||||
if (settingsKeys.contains("source") || force) {
|
||||
ostr << " m_source: " << m_source.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("title") || force) {
|
||||
ostr << " m_title: " << m_title.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor") || force) {
|
||||
ostr << " m_rgbColor: " << m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI") || force) {
|
||||
ostr << " m_useReverseAPI: " << m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("azimuth") || force) {
|
||||
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort") || force) {
|
||||
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureSetIndex") || force) {
|
||||
ostr << " m_reverseAPIFeatureSetIndex: " << m_reverseAPIFeatureSetIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex") || force) {
|
||||
ostr << " m_reverseAPIFeatureIndex: " << m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("azimuthOffset") || force) {
|
||||
ostr << " m_azimuthOffset: " << m_azimuthOffset;
|
||||
}
|
||||
@ -343,11 +364,32 @@ QString GS232ControllerSettings::getDebugString(const QStringList& settingsKeys,
|
||||
if (settingsKeys.contains("connection") || force) {
|
||||
ostr << " m_connection: " << m_connection;
|
||||
}
|
||||
if (settingsKeys.contains("host") || force) {
|
||||
ostr << " m_host: " << m_host.toStdString();
|
||||
if (settingsKeys.contains("precision") || force) {
|
||||
ostr << " m_precision: " << m_precision;
|
||||
}
|
||||
if (settingsKeys.contains("port") || force) {
|
||||
ostr << " m_port: " << m_port;
|
||||
if (settingsKeys.contains("coordinates") || force) {
|
||||
ostr << " m_coordinates: " << m_precision;
|
||||
}
|
||||
if (settingsKeys.contains("title") || force) {
|
||||
ostr << " m_title: " << m_title.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor") || force) {
|
||||
ostr << " m_rgbColor: " << m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI") || force) {
|
||||
ostr << " m_useReverseAPI: " << m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("azimuth") || force) {
|
||||
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort") || force) {
|
||||
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureSetIndex") || force) {
|
||||
ostr << " m_reverseAPIFeatureSetIndex: " << m_reverseAPIFeatureSetIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex") || force) {
|
||||
ostr << " m_reverseAPIFeatureIndex: " << m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("workspaceIndex") || force) {
|
||||
ostr << " m_workspaceIndex: " << m_workspaceIndex;
|
||||
@ -355,3 +397,4 @@ QString GS232ControllerSettings::getDebugString(const QStringList& settingsKeys,
|
||||
|
||||
return QString(ostr.str().c_str());
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,16 @@ struct GS232ControllerSettings
|
||||
int m_elevationMin;
|
||||
int m_elevationMax;
|
||||
float m_tolerance;
|
||||
enum Protocol { GS232, SPID, ROTCTLD } m_protocol;
|
||||
enum Protocol { GS232, SPID, ROTCTLD, DFM } m_protocol;
|
||||
enum Connection { SERIAL, TCP } m_connection;
|
||||
int m_precision;
|
||||
enum Coordinates { AZ_EL, X_Y_85, X_Y_30 } m_coordinates;
|
||||
|
||||
bool m_dfmTrackOn;
|
||||
bool m_dfmLubePumpsOn;
|
||||
bool m_dfmBrakesOn;
|
||||
bool m_dfmDrivesOn;
|
||||
|
||||
Serializable *m_rollupState;
|
||||
QString m_title;
|
||||
quint32 m_rgbColor;
|
||||
|
@ -38,10 +38,11 @@ GS232ControllerWorker::GS232ControllerWorker() :
|
||||
m_pollTimer(this),
|
||||
m_lastAzimuth(-1.0f),
|
||||
m_lastElevation(-1.0f),
|
||||
m_spidSetOutstanding(false),
|
||||
m_spidSetSent(false),
|
||||
m_spidStatusSent(false),
|
||||
m_rotCtlDReadAz(false)
|
||||
m_controllerProtocol(nullptr)
|
||||
// m_spidSetOutstanding(false),
|
||||
// m_spidSetSent(false),
|
||||
// m_spidStatusSent(false),
|
||||
// m_rotCtlDReadAz(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -50,6 +51,7 @@ GS232ControllerWorker::~GS232ControllerWorker()
|
||||
qDebug() << "GS232ControllerWorker::~GS232ControllerWorker";
|
||||
stopWork();
|
||||
m_inputMessageQueue.clear();
|
||||
delete m_controllerProtocol;
|
||||
}
|
||||
|
||||
void GS232ControllerWorker::startWork()
|
||||
@ -115,6 +117,17 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
|
||||
{
|
||||
qDebug() << "GS232ControllerWorker::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force;
|
||||
|
||||
if ((settingsKeys.contains("protocol") && (settings.m_protocol != m_settings.m_protocol)) || force)
|
||||
{
|
||||
delete m_controllerProtocol;
|
||||
m_controllerProtocol = ControllerProtocol::create(settings.m_protocol);
|
||||
if (m_controllerProtocol)
|
||||
{
|
||||
m_controllerProtocol->setMessageQueue(m_msgQueueToFeature);
|
||||
m_controllerProtocol->setDevice(m_device);
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("connection") )
|
||||
{
|
||||
if (m_device && m_device->isOpen())
|
||||
@ -126,26 +139,39 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
|
||||
|
||||
if (settings.m_connection == GS232ControllerSettings::TCP)
|
||||
{
|
||||
if (settingsKeys.contains("host") || settingsKeys.contains("port") || force) {
|
||||
if (settingsKeys.contains("host") || settingsKeys.contains("port") || force)
|
||||
{
|
||||
m_device = openSocket(settings);
|
||||
if (m_controllerProtocol) {
|
||||
m_controllerProtocol->setDevice(m_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settingsKeys.contains("serialPort") || force) {
|
||||
if (settingsKeys.contains("serialPort") || force)
|
||||
{
|
||||
m_device = openSerialPort(settings);
|
||||
} else if (settingsKeys.contains("baudRate") || force) {
|
||||
if (m_controllerProtocol) {
|
||||
m_controllerProtocol->setDevice(m_device);
|
||||
}
|
||||
}
|
||||
else if (settingsKeys.contains("baudRate") || force)
|
||||
{
|
||||
m_serialPort.setBaudRate(settings.m_baudRate);
|
||||
}
|
||||
}
|
||||
|
||||
// Must update m_settings before calling setAzimuthElevation, so m_settings.m_protocol is correct
|
||||
if (force) {
|
||||
m_settings = settings;
|
||||
} else {
|
||||
m_settings.applySettings(settingsKeys, settings);
|
||||
}
|
||||
|
||||
if (m_controllerProtocol) {
|
||||
m_controllerProtocol->applySettings(settings, settingsKeys, force);
|
||||
}
|
||||
|
||||
if (m_device != nullptr)
|
||||
{
|
||||
// Apply offset then clamp
|
||||
@ -220,244 +246,35 @@ QIODevice *GS232ControllerWorker::openSocket(const GS232ControllerSettings& sett
|
||||
|
||||
void GS232ControllerWorker::setAzimuth(float azimuth)
|
||||
{
|
||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||
{
|
||||
QString cmd = QString("M%1\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0'));
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAzimuthElevation(azimuth, m_lastElevation);
|
||||
if (m_device && m_device->isOpen() && m_controllerProtocol) {
|
||||
m_controllerProtocol->setAzimuth(azimuth);
|
||||
}
|
||||
|
||||
m_lastAzimuth = azimuth;
|
||||
}
|
||||
|
||||
void GS232ControllerWorker::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||
{
|
||||
QString cmd = QString("W%1 %2\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0')).arg((int)std::round(elevation), 3, 10, QLatin1Char('0'));
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
if (m_device && m_device->isOpen() && m_controllerProtocol) {
|
||||
m_controllerProtocol->setAzimuthElevation(azimuth, elevation);
|
||||
}
|
||||
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||
{
|
||||
if (!m_spidSetSent && !m_spidStatusSent)
|
||||
{
|
||||
QByteArray cmd(13, (char)0);
|
||||
|
||||
cmd[0] = 0x57; // Start
|
||||
int h = std::round((azimuth + 360.0f) * 2.0f);
|
||||
cmd[1] = 0x30 | (h / 1000);
|
||||
cmd[2] = 0x30 | ((h % 1000) / 100);
|
||||
cmd[3] = 0x30 | ((h % 100) / 10);
|
||||
cmd[4] = 0x30 | (h % 10);
|
||||
cmd[5] = 2; // 2 degree per impulse
|
||||
int v = std::round((elevation + 360.0f) * 2.0f);
|
||||
cmd[6] = 0x30 | (v / 1000);
|
||||
cmd[7] = 0x30 | ((v % 1000) / 100);
|
||||
cmd[8] = 0x30 | ((v % 100) / 10);
|
||||
cmd[9] = 0x30 | (v % 10);
|
||||
cmd[10] = 2; // 2 degree per impulse
|
||||
cmd[11] = 0x2f; // Set cmd
|
||||
cmd[12] = 0x20; // End
|
||||
|
||||
m_device->write(cmd);
|
||||
|
||||
m_spidSetSent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "GS232ControllerWorker::setAzimuthElevation: Not sent, waiting for status reply";
|
||||
m_spidSetOutstanding = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString cmd = QString("P %1 %2\n").arg(azimuth).arg(elevation);
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
}
|
||||
m_lastAzimuth = azimuth;
|
||||
m_lastElevation = elevation;
|
||||
}
|
||||
|
||||
void GS232ControllerWorker::readData()
|
||||
{
|
||||
char buf[1024];
|
||||
qint64 len;
|
||||
|
||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||
{
|
||||
while (m_device->canReadLine())
|
||||
{
|
||||
len = m_device->readLine(buf, sizeof(buf));
|
||||
if (len != -1)
|
||||
{
|
||||
QString response = QString::fromUtf8(buf, len);
|
||||
// MD-02 can return AZ=-00 EL=-00 and other negative angles
|
||||
QRegularExpression re("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)");
|
||||
QRegularExpressionMatch match = re.match(response);
|
||||
if (match.hasMatch())
|
||||
{
|
||||
QString az = match.captured(1);
|
||||
QString el = match.captured(2);
|
||||
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
|
||||
}
|
||||
else if (response == "\r\n")
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "GS232ControllerWorker::readData - unexpected GS-232 response \"" << response << "\"";
|
||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 response: %1").arg(response)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||
{
|
||||
while (m_device->bytesAvailable() >= 12)
|
||||
{
|
||||
len = m_device->read(buf, 12);
|
||||
if ((len == 12) && (buf[0] == 0x57))
|
||||
{
|
||||
double az;
|
||||
double el;
|
||||
az = buf[1] * 100.0 + buf[2] * 10.0 + buf[3] + buf[4] / 10.0 - 360.0;
|
||||
el = buf[6] * 100.0 + buf[7] * 10.0 + buf[8] + buf[9] / 10.0 - 360.0;
|
||||
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az, el));
|
||||
if (m_spidStatusSent && m_spidSetSent) {
|
||||
qDebug() << "GS232ControllerWorker::readData - m_spidStatusSent and m_spidSetSent set simultaneously";
|
||||
}
|
||||
if (m_spidStatusSent) {
|
||||
m_spidStatusSent = false;
|
||||
}
|
||||
if (m_spidSetSent) {
|
||||
m_spidSetSent = false;
|
||||
}
|
||||
if (m_spidSetOutstanding)
|
||||
{
|
||||
m_spidSetOutstanding = false;
|
||||
setAzimuthElevation(m_lastAzimuth, m_lastElevation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray bytes(buf, (int)len);
|
||||
qWarning() << "GS232ControllerWorker::readData - unexpected SPID rot2prog response \"" << bytes.toHex() << "\"";
|
||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected SPID rot2prog response: %1").arg(bytes.toHex().data())));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (m_device->canReadLine())
|
||||
{
|
||||
len = m_device->readLine(buf, sizeof(buf));
|
||||
if (len != -1)
|
||||
{
|
||||
QString response = QString::fromUtf8(buf, len).trimmed();
|
||||
QRegularExpression rprt("RPRT (-?\\d+)");
|
||||
QRegularExpressionMatch matchRprt = rprt.match(response);
|
||||
QRegularExpression decimal("(-?\\d+.\\d+)");
|
||||
QRegularExpressionMatch matchDecimal = decimal.match(response);
|
||||
if (matchRprt.hasMatch())
|
||||
{
|
||||
// See rig_errcode_e in hamlib rig.h
|
||||
const QStringList errors = {
|
||||
"OK",
|
||||
"Invalid parameter",
|
||||
"Invalid configuration",
|
||||
"No memory",
|
||||
"Not implemented",
|
||||
"Timeout",
|
||||
"IO error",
|
||||
"Internal error",
|
||||
"Protocol error",
|
||||
"Command rejected",
|
||||
"Arg truncated",
|
||||
"Not available",
|
||||
"VFO not targetable",
|
||||
"Bus error",
|
||||
"Collision on bus",
|
||||
"NULL rig handled or invalid pointer parameter",
|
||||
"Invalid VFO",
|
||||
"Argument out of domain of function"
|
||||
};
|
||||
int rprt = matchRprt.captured(1).toInt();
|
||||
if (rprt != 0)
|
||||
{
|
||||
qWarning() << "GS232ControllerWorker::readData - rotctld error: " << errors[-rprt];
|
||||
// Seem to get a lot of EPROTO errors from rotctld due to extra 00 char in response to GS232 C2 command
|
||||
// E.g: ./rotctld.exe -m 603 -r com7 -vvvvv
|
||||
// read_string(): RX 16 characters
|
||||
// 0000 00 41 5a 3d 31 37 35 20 20 45 4c 3d 30 33 38 0d .AZ=175 EL=038.
|
||||
// So don't pass these to GUI for now
|
||||
if (rprt != -8) {
|
||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("rotctld error: %1").arg(errors[-rprt])));
|
||||
}
|
||||
}
|
||||
m_rotCtlDReadAz = false;
|
||||
}
|
||||
else if (matchDecimal.hasMatch() && !m_rotCtlDReadAz)
|
||||
{
|
||||
m_rotCtlDAz = response;
|
||||
m_rotCtlDReadAz = true;
|
||||
}
|
||||
else if (matchDecimal.hasMatch() && m_rotCtlDReadAz)
|
||||
{
|
||||
QString az = m_rotCtlDAz;
|
||||
QString el = response;
|
||||
m_rotCtlDReadAz = false;
|
||||
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "GS232ControllerWorker::readData - Unexpected rotctld response \"" << response << "\"";
|
||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected rotctld response: %1").arg(response)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_controllerProtocol) {
|
||||
m_controllerProtocol->readData();
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerWorker::update()
|
||||
{
|
||||
// Request current Az/El from controller
|
||||
if (m_device && m_device->isOpen())
|
||||
{
|
||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||
{
|
||||
QByteArray cmd("C2\r\n");
|
||||
m_device->write(cmd);
|
||||
}
|
||||
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||
{
|
||||
// Don't send a new status command, if waiting for a previous reply
|
||||
if (!m_spidSetSent && !m_spidStatusSent)
|
||||
{
|
||||
// Status
|
||||
QByteArray cmd;
|
||||
cmd.append((char)0x57); // Start
|
||||
for (int i = 0; i < 10; i++) {
|
||||
cmd.append((char)0x0);
|
||||
}
|
||||
cmd.append((char)0x1f); // Status
|
||||
cmd.append((char)0x20); // End
|
||||
m_device->write(cmd);
|
||||
m_spidStatusSent = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray cmd("p\n");
|
||||
m_device->write(cmd);
|
||||
}
|
||||
if (m_device && m_device->isOpen() && m_controllerProtocol) {
|
||||
m_controllerProtocol->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "gs232controllersettings.h"
|
||||
#include "controllerprotocol.h"
|
||||
|
||||
class GS232ControllerWorker : public QObject
|
||||
{
|
||||
@ -81,12 +82,7 @@ private:
|
||||
float m_lastAzimuth;
|
||||
float m_lastElevation;
|
||||
|
||||
bool m_spidSetOutstanding;
|
||||
bool m_spidSetSent;
|
||||
bool m_spidStatusSent;
|
||||
|
||||
bool m_rotCtlDReadAz; //!< rotctrld returns 'p' responses over two lines
|
||||
QString m_rotCtlDAz;
|
||||
ControllerProtocol *m_controllerProtocol;
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
void applySettings(const GS232ControllerSettings& settings, const QList<QString>& settingsKeys, bool force = false);
|
||||
@ -102,3 +98,4 @@ private slots:
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GS232CONTROLLERWORKER_H_
|
||||
|
||||
|
86
plugins/feature/gs232controller/gs232protocol.cpp
Normal file
86
plugins/feature/gs232controller/gs232protocol.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 <cmath>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "gs232protocol.h"
|
||||
|
||||
GS232Protocol::GS232Protocol()
|
||||
{
|
||||
}
|
||||
|
||||
void GS232Protocol::setAzimuth(float azimuth)
|
||||
{
|
||||
QString cmd = QString("M%1\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0'));
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
m_lastAzimuth = azimuth;
|
||||
}
|
||||
|
||||
void GS232Protocol::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
QString cmd = QString("W%1 %2\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0')).arg((int)std::round(elevation), 3, 10, QLatin1Char('0'));
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
ControllerProtocol::setAzimuthElevation(azimuth, elevation);
|
||||
}
|
||||
|
||||
// Handle data received from controller
|
||||
void GS232Protocol::readData()
|
||||
{
|
||||
char buf[1024];
|
||||
qint64 len;
|
||||
|
||||
while (m_device->canReadLine())
|
||||
{
|
||||
len = m_device->readLine(buf, sizeof(buf));
|
||||
if (len != -1)
|
||||
{
|
||||
QString response = QString::fromUtf8(buf, len);
|
||||
// MD-02 can return AZ=-00 EL=-00 and other negative angles
|
||||
QRegularExpression re("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)");
|
||||
QRegularExpressionMatch match = re.match(response);
|
||||
if (match.hasMatch())
|
||||
{
|
||||
QString az = match.captured(1);
|
||||
QString el = match.captured(2);
|
||||
//qDebug() << "SPIDProtocol::readData read Az " << az << " El " << el;
|
||||
reportAzEl(az.toFloat(), el.toFloat());
|
||||
}
|
||||
else if (response == "\r\n")
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "SPIDProtocol::readData - unexpected GS-232 response \"" << response << "\"";
|
||||
reportError(QString("Unexpected GS-232 response: %1").arg(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request current Az/El from controller
|
||||
void GS232Protocol::update()
|
||||
{
|
||||
QByteArray cmd("C2\r\n");
|
||||
m_device->write(cmd);
|
||||
}
|
||||
|
34
plugins/feature/gs232controller/gs232protocol.h
Normal file
34
plugins/feature/gs232controller/gs232protocol.h
Normal file
@ -0,0 +1,34 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_FEATURE_GS232PROTOCOL_H_
|
||||
#define INCLUDE_FEATURE_GS232PROTOCOL_H_
|
||||
|
||||
#include "controllerprotocol.h"
|
||||
|
||||
class GS232Protocol : public ControllerProtocol
|
||||
{
|
||||
public:
|
||||
GS232Protocol();
|
||||
void setAzimuth(float azimuth) override;
|
||||
void setAzimuthElevation(float azimuth, float elevation) override;
|
||||
void readData() override;
|
||||
void update() override;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GS232PROTOCOL_H_
|
||||
|
@ -92,6 +92,21 @@ This can prevent some rotators that have a limited accuracy from making unbenefi
|
||||
If this set to 0, every target azimuth and elevation received by the controller will be send to the rotator.
|
||||
If it is set to 2, then a change in azimuth of +-1 degree from the previous azimuth, would not be sent to the rotator.
|
||||
|
||||
<h3>20: Precision</h3>
|
||||
|
||||
Specifies the number of decimal places used for coordinates and the tolerance setting.
|
||||
For GS-232 this is fixed to 0. For SPID it is fixed to 1.
|
||||
|
||||
<h3>21: Coordinates</h3>
|
||||
|
||||
Specifies the coordinate system used by the GUI for entry and display of the position of the rotator. This can be:
|
||||
|
||||
* Az/El - For azimuth and elevation in degrees.
|
||||
* X/Y 85' - For X/Y coordinates in degrees. 0,0 is zenith. X is positive Southward. Y is positive Eastward.
|
||||
* X/Y 30' - For X/Y coordinates in degrees. 0,0 is zenith. X is positivie Eastward. Y is positive Northward.
|
||||
|
||||
Equations for translating between these coordinate systems can be found [here](https://ntrs.nasa.gov/citations/19670030005).
|
||||
|
||||
<h2>Protocol Implementations</h2>
|
||||
|
||||
<h3>GS-232 Protocol Implementation Notes</h3>
|
||||
|
118
plugins/feature/gs232controller/rotctrldprotocol.cpp
Normal file
118
plugins/feature/gs232controller/rotctrldprotocol.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 <QRegularExpression>
|
||||
|
||||
#include "rotctrldprotocol.h"
|
||||
|
||||
RotCtrlDProtocol::RotCtrlDProtocol() :
|
||||
m_rotCtlDReadAz(false)
|
||||
{
|
||||
}
|
||||
|
||||
void RotCtrlDProtocol::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
QString cmd = QString("P %1 %2\n").arg(azimuth).arg(elevation);
|
||||
QByteArray data = cmd.toLatin1();
|
||||
m_device->write(data);
|
||||
ControllerProtocol::setAzimuthElevation(azimuth, elevation);
|
||||
}
|
||||
|
||||
// Handle data received from rotctrld
|
||||
void RotCtrlDProtocol::readData()
|
||||
{
|
||||
char buf[1024];
|
||||
qint64 len;
|
||||
|
||||
while (m_device->canReadLine())
|
||||
{
|
||||
len = m_device->readLine(buf, sizeof(buf));
|
||||
if (len != -1)
|
||||
{
|
||||
QString response = QString::fromUtf8(buf, len).trimmed();
|
||||
QRegularExpression rprt("RPRT (-?\\d+)");
|
||||
QRegularExpressionMatch matchRprt = rprt.match(response);
|
||||
QRegularExpression decimal("(-?\\d+.\\d+)");
|
||||
QRegularExpressionMatch matchDecimal = decimal.match(response);
|
||||
if (matchRprt.hasMatch())
|
||||
{
|
||||
// See rig_errcode_e in hamlib rig.h
|
||||
const QStringList errors = {
|
||||
"OK",
|
||||
"Invalid parameter",
|
||||
"Invalid configuration",
|
||||
"No memory",
|
||||
"Not implemented",
|
||||
"Timeout",
|
||||
"IO error",
|
||||
"Internal error",
|
||||
"Protocol error",
|
||||
"Command rejected",
|
||||
"Arg truncated",
|
||||
"Not available",
|
||||
"VFO not targetable",
|
||||
"Bus error",
|
||||
"Collision on bus",
|
||||
"NULL rig handled or invalid pointer parameter",
|
||||
"Invalid VFO",
|
||||
"Argument out of domain of function"
|
||||
};
|
||||
int rprt = matchRprt.captured(1).toInt();
|
||||
if (rprt != 0)
|
||||
{
|
||||
qWarning() << "GS232ControllerWorker::readData - rotctld error: " << errors[-rprt];
|
||||
// Seem to get a lot of EPROTO errors from rotctld due to extra 00 char in response to GS232 C2 command
|
||||
// E.g: ./rotctld.exe -m 603 -r com7 -vvvvv
|
||||
// read_string(): RX 16 characters
|
||||
// 0000 00 41 5a 3d 31 37 35 20 20 45 4c 3d 30 33 38 0d .AZ=175 EL=038.
|
||||
// So don't pass these to GUI for now
|
||||
if (rprt != -8) {
|
||||
reportError(QString("rotctld error: %1").arg(errors[-rprt]));
|
||||
}
|
||||
}
|
||||
m_rotCtlDReadAz = false;
|
||||
}
|
||||
else if (matchDecimal.hasMatch() && !m_rotCtlDReadAz)
|
||||
{
|
||||
m_rotCtlDAz = response;
|
||||
m_rotCtlDReadAz = true;
|
||||
}
|
||||
else if (matchDecimal.hasMatch() && m_rotCtlDReadAz)
|
||||
{
|
||||
QString az = m_rotCtlDAz;
|
||||
QString el = response;
|
||||
m_rotCtlDReadAz = false;
|
||||
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||
reportAzEl(az.toFloat(), el.toFloat());
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "GS232ControllerWorker::readData - Unexpected rotctld response \"" << response << "\"";
|
||||
reportError(QString("Unexpected rotctld response: %1").arg(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request current Az/El from rotctrld
|
||||
void RotCtrlDProtocol::update()
|
||||
{
|
||||
QByteArray cmd("p\n");
|
||||
m_device->write(cmd);
|
||||
}
|
||||
|
36
plugins/feature/gs232controller/rotctrldprotocol.h
Normal file
36
plugins/feature/gs232controller/rotctrldprotocol.h
Normal file
@ -0,0 +1,36 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_FEATURE_ROTCTRLDPROTOCOL_H_
|
||||
#define INCLUDE_FEATURE_ROTCTRLDPROTOCOL_H_
|
||||
|
||||
#include "controllerprotocol.h"
|
||||
|
||||
class RotCtrlDProtocol : public ControllerProtocol
|
||||
{
|
||||
public:
|
||||
RotCtrlDProtocol();
|
||||
void setAzimuthElevation(float azimuth, float elevation) override;
|
||||
void readData() override;
|
||||
void update() override;
|
||||
private:
|
||||
bool m_rotCtlDReadAz; //!< rotctrld returns 'p' responses over two lines
|
||||
QString m_rotCtlDAz;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_ROTCTRLDPROTOCOL_H_
|
||||
|
124
plugins/feature/gs232controller/spidprotocol.cpp
Normal file
124
plugins/feature/gs232controller/spidprotocol.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 <cmath>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "spidprotocol.h"
|
||||
|
||||
SPIDProtocol::SPIDProtocol() :
|
||||
m_spidStatusSent(false),
|
||||
m_spidSetSent(false),
|
||||
m_spidSetOutstanding(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SPIDProtocol::setAzimuthElevation(float azimuth, float elevation)
|
||||
{
|
||||
if (!m_spidSetSent && !m_spidStatusSent)
|
||||
{
|
||||
QByteArray cmd(13, (char)0);
|
||||
|
||||
cmd[0] = 0x57; // Start
|
||||
int h = std::round((azimuth + 360.0f) * 2.0f);
|
||||
cmd[1] = 0x30 | (h / 1000);
|
||||
cmd[2] = 0x30 | ((h % 1000) / 100);
|
||||
cmd[3] = 0x30 | ((h % 100) / 10);
|
||||
cmd[4] = 0x30 | (h % 10);
|
||||
cmd[5] = 2; // 2 degree per impulse
|
||||
int v = std::round((elevation + 360.0f) * 2.0f);
|
||||
cmd[6] = 0x30 | (v / 1000);
|
||||
cmd[7] = 0x30 | ((v % 1000) / 100);
|
||||
cmd[8] = 0x30 | ((v % 100) / 10);
|
||||
cmd[9] = 0x30 | (v % 10);
|
||||
cmd[10] = 2; // 2 degree per impulse
|
||||
cmd[11] = 0x2f; // Set cmd
|
||||
cmd[12] = 0x20; // End
|
||||
|
||||
m_device->write(cmd);
|
||||
|
||||
m_spidSetSent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "SPIDProtocol::setAzimuthElevation: Not sent, waiting for status reply";
|
||||
m_spidSetOutstanding = true;
|
||||
}
|
||||
ControllerProtocol::setAzimuthElevation(azimuth, elevation);
|
||||
}
|
||||
|
||||
// Handle data received from controller
|
||||
void SPIDProtocol::readData()
|
||||
{
|
||||
char buf[1024];
|
||||
qint64 len;
|
||||
|
||||
while (m_device->bytesAvailable() >= 12)
|
||||
{
|
||||
len = m_device->read(buf, 12);
|
||||
if ((len == 12) && (buf[0] == 0x57))
|
||||
{
|
||||
double az;
|
||||
double el;
|
||||
az = buf[1] * 100.0 + buf[2] * 10.0 + buf[3] + buf[4] / 10.0 - 360.0;
|
||||
el = buf[6] * 100.0 + buf[7] * 10.0 + buf[8] + buf[9] / 10.0 - 360.0;
|
||||
//qDebug() << "SPIDProtocol::readData read Az " << az << " El " << el;
|
||||
reportAzEl(az, el);
|
||||
if (m_spidStatusSent && m_spidSetSent) {
|
||||
qDebug() << "SPIDProtocol::readData - m_spidStatusSent and m_spidSetSent set simultaneously";
|
||||
}
|
||||
if (m_spidStatusSent) {
|
||||
m_spidStatusSent = false;
|
||||
}
|
||||
if (m_spidSetSent) {
|
||||
m_spidSetSent = false;
|
||||
}
|
||||
if (m_spidSetOutstanding)
|
||||
{
|
||||
m_spidSetOutstanding = false;
|
||||
setAzimuthElevation(m_lastAzimuth, m_lastElevation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray bytes(buf, (int)len);
|
||||
qWarning() << "SPIDProtocol::readData - unexpected SPID rot2prog response \"" << bytes.toHex() << "\"";
|
||||
reportError(QString("Unexpected SPID rot2prog response: %1").arg(bytes.toHex().data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request current Az/El from controller
|
||||
void SPIDProtocol::update()
|
||||
{
|
||||
// Don't send a new status command, if waiting for a previous reply
|
||||
if (!m_spidSetSent && !m_spidStatusSent)
|
||||
{
|
||||
// Status
|
||||
QByteArray cmd;
|
||||
cmd.append((char)0x57); // Start
|
||||
for (int i = 0; i < 10; i++) {
|
||||
cmd.append((char)0x0);
|
||||
}
|
||||
cmd.append((char)0x1f); // Status
|
||||
cmd.append((char)0x20); // End
|
||||
m_device->write(cmd);
|
||||
m_spidStatusSent = true;
|
||||
}
|
||||
}
|
||||
|
37
plugins/feature/gs232controller/spidprotocol.h
Normal file
37
plugins/feature/gs232controller/spidprotocol.h
Normal file
@ -0,0 +1,37 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// 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 INCLUDE_FEATURE_SPIDPROTOCOL_H_
|
||||
#define INCLUDE_FEATURE_SPIDPROTOCOL_H_
|
||||
|
||||
#include "controllerprotocol.h"
|
||||
|
||||
class SPIDProtocol : public ControllerProtocol
|
||||
{
|
||||
public:
|
||||
SPIDProtocol();
|
||||
void setAzimuthElevation(float azimuth, float elevation) override;
|
||||
void readData() override;
|
||||
void update() override;
|
||||
private:
|
||||
bool m_spidStatusSent;
|
||||
bool m_spidSetSent;
|
||||
bool m_spidSetOutstanding;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_SPIDPROTOCOL_H_
|
||||
|
@ -116,7 +116,10 @@ On the display tab, you can set:
|
||||
* The default frequency in MHz that is used for calculating Doppler and free space path loss in the Satellite Data table.
|
||||
* The units used to display azimuth and elevation to the target satellite. This can be in degrees, minutes and seconds or decimal degrees.
|
||||
* The number of points used for ground tracks on the map. More points result in smoother tracks, but require more processing.
|
||||
* Whether times are displayrf in the local time zone or UTC.
|
||||
* Which rotators are displayed on the polar chart. This can be All, None or Matching target. When Matching target is selected, the rotator will
|
||||
only be displayed if the source in the Rotator Controller is set to this Satellite Tracker and Track is enabled.
|
||||
* The format used for displaying dates. E.g. yyyy/MM/dd
|
||||
* Whether times are displayed in the local time zone or UTC.
|
||||
* Whether to draw the satellites on the map.
|
||||
|
||||
<h3>9: Latitude</h3>
|
||||
|
@ -28,8 +28,10 @@
|
||||
|
||||
#include "device/deviceapi.h"
|
||||
#include "device/deviceset.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "feature/featureset.h"
|
||||
#include "feature/featureuiset.h"
|
||||
#include "feature/featureutils.h"
|
||||
#include "feature/featurewebapiutils.h"
|
||||
#include "gui/basicfeaturesettingsdialog.h"
|
||||
#include "gui/dialogpositioner.h"
|
||||
@ -295,6 +297,8 @@ SatelliteTrackerGUI::SatelliteTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *fea
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(1000);
|
||||
|
||||
connect(&m_redrawTimer, &QTimer::timeout, this, &SatelliteTrackerGUI::plotChart);
|
||||
|
||||
// Intialise charts
|
||||
m_emptyChart.layout()->setContentsMargins(0, 0, 0, 0);
|
||||
m_emptyChart.setMargins(QMargins(1, 1, 1, 1));
|
||||
@ -534,6 +538,7 @@ void SatelliteTrackerGUI::on_displaySettings_clicked()
|
||||
m_settingsKeys.append("defaultFrequency");
|
||||
m_settingsKeys.append("azElUnits");
|
||||
m_settingsKeys.append("groundTrackPoints");
|
||||
m_settingsKeys.append("drawRotators");
|
||||
m_settingsKeys.append("dateFormat");
|
||||
m_settingsKeys.append("utc");
|
||||
m_settingsKeys.append("tles");
|
||||
@ -792,6 +797,26 @@ static double interpolate(double x0, double y0, double x1, double y1, double x)
|
||||
return (y0*(x1-x) + y1*(x-x0)) / (x1-x0);
|
||||
}
|
||||
|
||||
// Reduce az/el range from 450,180 to 360,90
|
||||
void SatelliteTrackerGUI::limitAzElRange(double& azimuth, double& elevation) const
|
||||
{
|
||||
if (elevation > 90.0)
|
||||
{
|
||||
elevation = 180.0 - elevation;
|
||||
if (azimuth < 180.0) {
|
||||
azimuth += 180.0;
|
||||
} else {
|
||||
azimuth -= 180.0;
|
||||
}
|
||||
}
|
||||
if (azimuth > 360.0) {
|
||||
azimuth -= 360.0f;
|
||||
}
|
||||
if (azimuth == 0) {
|
||||
azimuth = 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Plot pass in polar coords
|
||||
void SatelliteTrackerGUI::plotPolarChart()
|
||||
{
|
||||
@ -916,6 +941,86 @@ void SatelliteTrackerGUI::plotPolarChart()
|
||||
series[i]->attachAxis(radialAxis);
|
||||
}
|
||||
|
||||
int redrawTime = 0;
|
||||
|
||||
if (m_settings.m_drawRotators != SatelliteTrackerSettings::NO_ROTATORS)
|
||||
{
|
||||
// Plot rotator position
|
||||
QString ourSourceName = QString("F0:%1 %2").arg(m_satelliteTracker->getIndexInFeatureSet()).arg(m_satelliteTracker->getIdentifier()); // Only one feature set in practice?
|
||||
std::vector<FeatureSet*>& featureSets = MainCore::instance()->getFeatureeSets();
|
||||
for (int featureSetIndex = 0; featureSetIndex < featureSets.size(); featureSetIndex++)
|
||||
{
|
||||
FeatureSet *featureSet = featureSets[featureSetIndex];
|
||||
for (int featureIndex = 0; featureIndex < featureSet->getNumberOfFeatures(); featureIndex++)
|
||||
{
|
||||
Feature *feature = featureSet->getFeatureAt(featureIndex);
|
||||
if (FeatureUtils::compareFeatureURIs(feature->getURI(), "sdrangel.feature.gs232controller"))
|
||||
{
|
||||
QString source;
|
||||
ChannelWebAPIUtils::getFeatureSetting(featureSetIndex, featureIndex, "source", source); // Will return false if source isn't set in Controller
|
||||
int track = 0;
|
||||
ChannelWebAPIUtils::getFeatureSetting(featureSetIndex, featureIndex, "track", track);
|
||||
if ((m_settings.m_drawRotators == SatelliteTrackerSettings::ALL_ROTATORS) || ((source == ourSourceName) && track))
|
||||
{
|
||||
int onTarget = 0;
|
||||
ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "onTarget", onTarget);
|
||||
|
||||
if (!onTarget)
|
||||
{
|
||||
// Target azimuth red dotted line
|
||||
double targetAzimuth, targetElevation;
|
||||
bool targetAzimuthOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "targetAzimuth", targetAzimuth);
|
||||
bool targetElevationOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "targetElevation", targetElevation);
|
||||
if (targetAzimuthOk && targetElevationOk)
|
||||
{
|
||||
limitAzElRange(targetAzimuth, targetElevation);
|
||||
|
||||
QScatterSeries *rotatorSeries = new QScatterSeries();
|
||||
QColor color(255, 0, 0, 150);
|
||||
QPen pen(color);
|
||||
rotatorSeries->setPen(pen);
|
||||
rotatorSeries->setColor(color.darker());
|
||||
rotatorSeries->setMarkerSize(20);
|
||||
rotatorSeries->append(targetAzimuth, 90-targetElevation);
|
||||
m_polarChart->addSeries(rotatorSeries);
|
||||
rotatorSeries->attachAxis(angularAxis);
|
||||
rotatorSeries->attachAxis(radialAxis);
|
||||
|
||||
redrawTime = 333;
|
||||
}
|
||||
}
|
||||
|
||||
// Current azimuth line. Yellow while off target, green on target.
|
||||
double currentAzimuth, currentElevation;
|
||||
bool currentAzimuthOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "currentAzimuth", currentAzimuth);
|
||||
bool currentElevationOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "currentElevation", currentElevation);
|
||||
if (currentAzimuthOk && currentElevationOk)
|
||||
{
|
||||
limitAzElRange(currentAzimuth, currentElevation);
|
||||
|
||||
QScatterSeries *rotatorSeries = new QScatterSeries();
|
||||
QColor color;
|
||||
if (onTarget) {
|
||||
color = QColor(0, 255, 0, 150);
|
||||
} else {
|
||||
color = QColor(255, 255, 0, 150);
|
||||
}
|
||||
rotatorSeries->setPen(QPen(color));
|
||||
rotatorSeries->setColor(color.darker());
|
||||
rotatorSeries->setMarkerSize(20);
|
||||
rotatorSeries->append(currentAzimuth, 90-currentElevation);
|
||||
m_polarChart->addSeries(rotatorSeries);
|
||||
rotatorSeries->attachAxis(angularAxis);
|
||||
rotatorSeries->attachAxis(radialAxis);
|
||||
|
||||
redrawTime = 333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create series with single point, so we can plot time of AOS
|
||||
QLineSeries *aosSeries = new QLineSeries();
|
||||
aosSeries->append(polarSeries->at(0));
|
||||
@ -967,7 +1072,8 @@ void SatelliteTrackerGUI::plotPolarChart()
|
||||
if ((currentTime >= pass.m_aos) && (currentTime <= pass.m_los))
|
||||
{
|
||||
// Create series with single point, so we can plot current time
|
||||
QLineSeries *nowSeries = new QLineSeries();
|
||||
QScatterSeries *nowSeries = new QScatterSeries();
|
||||
nowSeries->setMarkerSize(3);
|
||||
// Find closest point to current time
|
||||
int idx = std::round(polarSeries->count() * (currentTime.toMSecsSinceEpoch() - pass.m_aos.toMSecsSinceEpoch())
|
||||
/ (pass.m_los.toMSecsSinceEpoch() - pass.m_aos.toMSecsSinceEpoch()));
|
||||
@ -978,8 +1084,16 @@ void SatelliteTrackerGUI::plotPolarChart()
|
||||
m_polarChart->addSeries(nowSeries);
|
||||
nowSeries->attachAxis(angularAxis);
|
||||
nowSeries->attachAxis(radialAxis);
|
||||
// Redraw in 5 seconds (call plotChart, incase user selects a different chart)
|
||||
QTimer::singleShot(5000, this, &SatelliteTrackerGUI::plotChart);
|
||||
if (!redrawTime) {
|
||||
redrawTime = 5000;
|
||||
}
|
||||
}
|
||||
|
||||
if (redrawTime > 0)
|
||||
{
|
||||
// Redraw to show updated satellite position or rotator position
|
||||
m_redrawTimer.setSingleShot(true);
|
||||
m_redrawTimer.start(redrawTime);
|
||||
}
|
||||
|
||||
delete polarSeries;
|
||||
@ -1567,3 +1681,4 @@ void SatelliteTrackerGUI::makeUIConnections()
|
||||
QObject::connect(ui->satTable->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &SatelliteTrackerGUI::on_satTableHeader_sortIndicatorChanged);
|
||||
QObject::connect(ui->deviceFeatureSelect, qOverload<int>(&QComboBox::currentIndexChanged), this, &SatelliteTrackerGUI::on_deviceFeatureSelect_currentIndexChanged);
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ private:
|
||||
QChart m_emptyChart;
|
||||
QChart *m_lineChart;
|
||||
QPolarChart *m_polarChart;
|
||||
QTimer m_redrawTimer;
|
||||
|
||||
QDateTime m_nextTargetAOS;
|
||||
QDateTime m_nextTargetLOS;
|
||||
@ -138,6 +139,7 @@ private:
|
||||
void updateFileInputList();
|
||||
void updateMapList();
|
||||
void makeUIConnections();
|
||||
void limitAzElRange(double& azimuth, double& elevation) const;
|
||||
|
||||
private slots:
|
||||
void onMenuDialogCalled(const QPoint &p);
|
||||
|
@ -79,6 +79,7 @@ void SatelliteTrackerSettings::resetToDefaults()
|
||||
m_dateTimeSelect = NOW;
|
||||
m_mapFeature = "";
|
||||
m_fileInputDevice = "";
|
||||
m_drawRotators = MATCHING_TARGET;
|
||||
m_workspaceIndex = 0;
|
||||
m_columnSort = -1;
|
||||
m_columnSortOrder = Qt::AscendingOrder;
|
||||
@ -142,6 +143,7 @@ QByteArray SatelliteTrackerSettings::serialize() const
|
||||
s.writeBlob(46, m_geometryBytes);
|
||||
s.writeS32(47, m_columnSort);
|
||||
s.writeS32(48, (int)m_columnSortOrder);
|
||||
s.writeS32(49, (int)m_drawRotators);
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
s.writeS32(100 + i, m_columnIndexes[i]);
|
||||
@ -237,6 +239,7 @@ bool SatelliteTrackerSettings::deserialize(const QByteArray& data)
|
||||
d.readBlob(46, &m_geometryBytes);
|
||||
d.readS32(47, &m_columnSort, -1);
|
||||
d.readS32(48, (int *)&m_columnSortOrder, (int)Qt::AscendingOrder);
|
||||
d.readS32(49, (int*)&m_drawRotators, (int)MATCHING_TARGET);
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_columnIndexes[i], i);
|
||||
@ -398,6 +401,15 @@ void SatelliteTrackerSettings::applySettings(const QStringList& settingsKeys, co
|
||||
if (settingsKeys.contains("dopplerPeriod")) {
|
||||
m_dopplerPeriod = settings.m_dopplerPeriod;
|
||||
}
|
||||
if (settingsKeys.contains("predictionPeriod")) {
|
||||
m_predictionPeriod = settings.m_predictionPeriod;
|
||||
}
|
||||
if (settingsKeys.contains("passStartTime")) {
|
||||
m_passStartTime = settings.m_passStartTime;
|
||||
}
|
||||
if (settingsKeys.contains("passFinishTime")) {
|
||||
m_passFinishTime = settings.m_passFinishTime;
|
||||
}
|
||||
if (settingsKeys.contains("defaultFrequency")) {
|
||||
m_defaultFrequency = settings.m_defaultFrequency;
|
||||
}
|
||||
@ -410,23 +422,59 @@ void SatelliteTrackerSettings::applySettings(const QStringList& settingsKeys, co
|
||||
if (settingsKeys.contains("aosSpeech")) {
|
||||
m_aosSpeech = settings.m_aosSpeech;
|
||||
}
|
||||
if (settingsKeys.contains("aosCommand")) {
|
||||
m_aosCommand = settings.m_aosCommand;
|
||||
}
|
||||
if (settingsKeys.contains("losSpeech")) {
|
||||
m_losSpeech = settings.m_losSpeech;
|
||||
}
|
||||
if (settingsKeys.contains("aosCommand")) {
|
||||
m_aosCommand = settings.m_aosCommand;
|
||||
}
|
||||
if (settingsKeys.contains("losCommand")) {
|
||||
m_losCommand = settings.m_losCommand;
|
||||
}
|
||||
if (settingsKeys.contains("predictionPeriod")) {
|
||||
m_predictionPeriod = settings.m_predictionPeriod;
|
||||
if (settingsKeys.contains("chartsDarkTheme")) {
|
||||
m_chartsDarkTheme = settings.m_chartsDarkTheme;
|
||||
}
|
||||
if (settingsKeys.contains("passStartTime")) {
|
||||
m_passStartTime = settings.m_passStartTime;
|
||||
if (settingsKeys.contains("deviceSettings")) {
|
||||
m_deviceSettings = settings.m_deviceSettings;
|
||||
}
|
||||
if (settingsKeys.contains("passFinishTime")) {
|
||||
m_passFinishTime = settings.m_passFinishTime;
|
||||
if (settingsKeys.contains("replayEnabled")) {
|
||||
m_replayEnabled = settings.m_replayEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("replayStartDateTime")) {
|
||||
m_replayStartDateTime = settings.m_replayStartDateTime;
|
||||
}
|
||||
if (settingsKeys.contains("sendTimeToMap")) {
|
||||
m_sendTimeToMap = settings.m_sendTimeToMap;
|
||||
}
|
||||
if (settingsKeys.contains("dateTimeSelect")) {
|
||||
m_dateTimeSelect = settings.m_dateTimeSelect;
|
||||
}
|
||||
if (settingsKeys.contains("mapFeature")) {
|
||||
m_mapFeature = settings.m_mapFeature;
|
||||
}
|
||||
if (settingsKeys.contains("fileInputDevice")) {
|
||||
m_fileInputDevice = settings.m_fileInputDevice;
|
||||
}
|
||||
if (settingsKeys.contains("drawRotators")) {
|
||||
m_drawRotators = settings.m_drawRotators;
|
||||
}
|
||||
if (settingsKeys.contains("columnSort")) {
|
||||
m_columnSort = settings.m_columnSort;
|
||||
}
|
||||
if (settingsKeys.contains("columnSortOrder")) {
|
||||
m_columnSortOrder = settings.m_columnSortOrder;
|
||||
}
|
||||
if (settingsKeys.contains("columnIndexes"))
|
||||
{
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
m_columnIndexes[i] = settings.m_columnIndexes[i];
|
||||
}
|
||||
}
|
||||
if (settingsKeys.contains("columnSizes"))
|
||||
{
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
m_columnSizes[i] = settings.m_columnSizes[i];
|
||||
}
|
||||
}
|
||||
if (settingsKeys.contains("title")) {
|
||||
m_title = settings.m_title;
|
||||
@ -449,44 +497,8 @@ void SatelliteTrackerSettings::applySettings(const QStringList& settingsKeys, co
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex")) {
|
||||
m_reverseAPIFeatureIndex = settings.m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("chartsDarkTheme")) {
|
||||
m_chartsDarkTheme = settings.m_chartsDarkTheme;
|
||||
}
|
||||
if (settingsKeys.contains("replayEnabled")) {
|
||||
m_replayEnabled = settings.m_replayEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("replayStartDateTime")) {
|
||||
m_replayStartDateTime = settings.m_replayStartDateTime;
|
||||
}
|
||||
if (settingsKeys.contains("sendTimeToMap")) {
|
||||
m_sendTimeToMap = settings.m_sendTimeToMap;
|
||||
}
|
||||
if (settingsKeys.contains("dateTimeSelect")) {
|
||||
m_dateTimeSelect = settings.m_dateTimeSelect;
|
||||
}
|
||||
if (settingsKeys.contains("columnSort")) {
|
||||
m_columnSort = settings.m_columnSort;
|
||||
}
|
||||
if (settingsKeys.contains("columnSortOrder")) {
|
||||
m_columnSortOrder = settings.m_columnSortOrder;
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("columnIndexes"))
|
||||
{
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
m_columnIndexes[i] = settings.m_columnIndexes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("columnSizes"))
|
||||
{
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
m_columnSizes[i] = settings.m_columnSizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("deviceSettings")) {
|
||||
m_deviceSettings = settings.m_deviceSettings;
|
||||
if (settingsKeys.contains("workspaceIndex")) {
|
||||
m_workspaceIndex = settings.m_workspaceIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +515,9 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
if (settingsKeys.contains("heightAboveSeaLevel") || force) {
|
||||
ostr << " m_heightAboveSeaLevel: " << m_heightAboveSeaLevel;
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("target") || force) {
|
||||
ostr << " m_target: " << m_target.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("satellites") || force)
|
||||
{
|
||||
ostr << "m_satellites:";
|
||||
@ -512,7 +526,6 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
ostr << " " << satellite.toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("tles") || force)
|
||||
{
|
||||
ostr << " m_tles:";
|
||||
@ -521,7 +534,6 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
ostr << " " << tle.toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("dateTime") || force) {
|
||||
ostr << " m_dateTime: " << m_dateTime.toStdString();
|
||||
}
|
||||
@ -555,6 +567,15 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
if (settingsKeys.contains("dopplerPeriod") || force) {
|
||||
ostr << " m_dopplerPeriod: " << m_dopplerPeriod;
|
||||
}
|
||||
if (settingsKeys.contains("predictionPeriod") || force) {
|
||||
ostr << " m_predictionPeriod: " << m_predictionPeriod;
|
||||
}
|
||||
if (settingsKeys.contains("passStartTime") || force) {
|
||||
ostr << " m_passStartTime: " << m_passStartTime.toString().toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("passFinishTime") || force) {
|
||||
ostr << " m_passFinishTime: " << m_passFinishTime.toString().toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("defaultFrequency") || force) {
|
||||
ostr << " m_defaultFrequency: " << m_defaultFrequency;
|
||||
}
|
||||
@ -576,14 +597,68 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
if (settingsKeys.contains("losCommand") || force) {
|
||||
ostr << " m_losCommand: " << m_losCommand.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("predictionPeriod") || force) {
|
||||
ostr << " m_predictionPeriod: " << m_predictionPeriod;
|
||||
if (settingsKeys.contains("chartsDarkTheme") || force) {
|
||||
ostr << " m_chartsDarkTheme: " << m_chartsDarkTheme;
|
||||
}
|
||||
if (settingsKeys.contains("passStartTime") || force) {
|
||||
ostr << " m_passStartTime: " << m_passStartTime.toString().toStdString();
|
||||
if (settingsKeys.contains("deviceSettings"))
|
||||
{
|
||||
ostr << "m_deviceSettings: [";
|
||||
|
||||
for (auto deviceSettingList : m_deviceSettings)
|
||||
{
|
||||
ostr << "[";
|
||||
|
||||
for (auto deviceSettings : *deviceSettingList) {
|
||||
deviceSettings->getDebugString(ostr);
|
||||
}
|
||||
|
||||
ostr << "]";
|
||||
}
|
||||
|
||||
ostr << "]";
|
||||
}
|
||||
if (settingsKeys.contains("passFinishTime") || force) {
|
||||
ostr << " m_passFinishTime: " << m_passFinishTime.toString().toStdString();
|
||||
if (settingsKeys.contains("replayEnabled") || force) {
|
||||
ostr << " m_replayEnabled: " << m_replayEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("replayStartDateTime") || force) {
|
||||
ostr << " m_replayStartDateTime: " << m_replayStartDateTime.toString().toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("sendTimeToMap") || force) {
|
||||
ostr << " m_sendTimeToMap: " << m_sendTimeToMap;
|
||||
}
|
||||
if (settingsKeys.contains("dateTimeSelect") || force) {
|
||||
ostr << " m_dateTimeSelect: " << m_dateTimeSelect;
|
||||
}
|
||||
if (settingsKeys.contains("mapFeature") || force) {
|
||||
ostr << " m_mapFeature: " << m_mapFeature.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("fileInputDevice") || force) {
|
||||
ostr << " m_fileInputDevice: " << m_fileInputDevice.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("drawRotators") || force) {
|
||||
ostr << " m_drawRotators: " << m_drawRotators;
|
||||
}
|
||||
if (settingsKeys.contains("columnSort") || force) {
|
||||
ostr << " m_columnSort: " << m_columnSort;
|
||||
}
|
||||
if (settingsKeys.contains("columnSortOrder") || force) {
|
||||
ostr << " m_columnSortOrder: " << m_columnSortOrder;
|
||||
}
|
||||
if (settingsKeys.contains("columnIndexes"))
|
||||
{
|
||||
ostr << "m_columnIndexes:";
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
ostr << " " << m_columnIndexes[i];
|
||||
}
|
||||
}
|
||||
if (settingsKeys.contains("columnSizes"))
|
||||
{
|
||||
ostr << "m_columnSizes:";
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
ostr << " " << m_columnSizes[i];
|
||||
}
|
||||
}
|
||||
if (settingsKeys.contains("title") || force) {
|
||||
ostr << " m_title: " << m_title.toStdString();
|
||||
@ -606,72 +681,9 @@ QString SatelliteTrackerSettings::getDebugString(const QStringList& settingsKeys
|
||||
if (settingsKeys.contains("reverseAPIFeatureIndex") || force) {
|
||||
ostr << " m_reverseAPIFeatureIndex: " << m_reverseAPIFeatureIndex;
|
||||
}
|
||||
if (settingsKeys.contains("chartsDarkTheme") || force) {
|
||||
ostr << " m_chartsDarkTheme: " << m_chartsDarkTheme;
|
||||
}
|
||||
if (settingsKeys.contains("replayEnabled") || force) {
|
||||
ostr << " m_replayEnabled: " << m_replayEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("replayStartDateTime") || force) {
|
||||
ostr << " m_replayStartDateTime: " << m_replayStartDateTime.toString().toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("sendTimeToMap") || force) {
|
||||
ostr << " m_sendTimeToMap: " << m_sendTimeToMap;
|
||||
}
|
||||
if (settingsKeys.contains("dateTimeSelect") || force) {
|
||||
ostr << " m_dateTimeSelect: " << m_dateTimeSelect;
|
||||
}
|
||||
if (settingsKeys.contains("mapFeature") || force) {
|
||||
ostr << " m_mapFeature: " << m_mapFeature.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("fileInputDevice") || force) {
|
||||
ostr << " m_fileInputDevice: " << m_fileInputDevice.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("workspaceIndex") || force) {
|
||||
ostr << " m_workspaceIndex: " << m_workspaceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("columnSort") || force) {
|
||||
ostr << " m_columnSort: " << m_columnSort;
|
||||
}
|
||||
if (settingsKeys.contains("columnSortOrder") || force) {
|
||||
ostr << " m_columnSortOrder: " << m_columnSortOrder;
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("columnIndexes"))
|
||||
{
|
||||
ostr << "m_columnIndexes:";
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
ostr << " " << m_columnIndexes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("columnSizes"))
|
||||
{
|
||||
ostr << "m_columnSizes:";
|
||||
|
||||
for (int i = 0; i < SAT_COL_COLUMNS; i++) {
|
||||
ostr << " " << m_columnSizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("deviceSettings"))
|
||||
{
|
||||
ostr << "m_deviceSettings: [";
|
||||
|
||||
for (auto deviceSettingList : m_deviceSettings)
|
||||
{
|
||||
ostr << "[";
|
||||
|
||||
for (auto deviceSettings : *deviceSettingList) {
|
||||
deviceSettings->getDebugString(ostr);
|
||||
}
|
||||
|
||||
ostr << "]";
|
||||
}
|
||||
|
||||
ostr << "]";
|
||||
}
|
||||
|
||||
return QString(ostr.str().c_str());
|
||||
}
|
||||
@ -696,3 +708,4 @@ void SatelliteTrackerSettings::SatelliteDeviceSettings::getDebugString(std::ostr
|
||||
<< " m_aosCommand: " << m_aosCommand.toStdString()
|
||||
<< " m_losCommand: " << m_losCommand.toStdString();
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ struct SatelliteTrackerSettings
|
||||
enum DateTimeSelect {NOW, CUSTOM, FROM_MAP, FROM_FILE} m_dateTimeSelect;
|
||||
QString m_mapFeature; //!< Which feature when FROM_MAP
|
||||
QString m_fileInputDevice; //!< Which device when FROM_FILE
|
||||
enum Rotators {ALL_ROTATORS, NO_ROTATORS, MATCHING_TARGET} m_drawRotators; //!< Which rotators to draw on polar chart
|
||||
|
||||
int m_columnSort; //!< Which column is used for sorting (-1 for none)
|
||||
Qt::SortOrder m_columnSortOrder;
|
||||
|
@ -42,6 +42,7 @@ SatelliteTrackerSettingsDialog::SatelliteTrackerSettingsDialog(SatelliteTrackerS
|
||||
ui->defaultFrequency->setValue(settings->m_defaultFrequency / 1000000.0);
|
||||
ui->azElUnits->setCurrentIndex((int)settings->m_azElUnits);
|
||||
ui->groundTrackPoints->setValue(settings->m_groundTrackPoints);
|
||||
ui->drawRotators->setCurrentIndex((int)settings->m_drawRotators);
|
||||
ui->dateFormat->setText(settings->m_dateFormat);
|
||||
ui->utc->setChecked(settings->m_utc);
|
||||
ui->drawOnMap->setChecked(settings->m_drawOnMap);
|
||||
@ -94,6 +95,7 @@ void SatelliteTrackerSettingsDialog::accept()
|
||||
m_settings->m_defaultFrequency = (float)(ui->defaultFrequency->value() * 1000000.0);
|
||||
m_settings->m_azElUnits = (SatelliteTrackerSettings::AzElUnits)ui->azElUnits->currentIndex();
|
||||
m_settings->m_groundTrackPoints = ui->groundTrackPoints->value();
|
||||
m_settings->m_drawRotators = (SatelliteTrackerSettings::Rotators)ui->drawRotators->currentIndex();
|
||||
m_settings->m_dateFormat = ui->dateFormat->text();
|
||||
m_settings->m_utc = ui->utc->isChecked();
|
||||
m_settings->m_drawOnMap = ui->drawOnMap->isChecked();
|
||||
|
@ -339,75 +339,20 @@
|
||||
<string>Display</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="defaultFrequency">
|
||||
<property name="toolTip">
|
||||
<string>Frequency used for Doppler and free space path loss calculations in the satellite table</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>50000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="dateFormat">
|
||||
<property name="toolTip">
|
||||
<string>Format for dates displayed in the GUI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QCheckBox" name="drawOnMap">
|
||||
<widget class="QCheckBox" name="utc">
|
||||
<property name="toolTip">
|
||||
<string>When checked satellite positions are sent to the map</string>
|
||||
<string>When checked times are dispayed using UTC rather than the local time zone</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Draw satellites on map</string>
|
||||
<string>Display times in UTC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="updatePeriodLabel">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="groundTrackPointsLabel">
|
||||
<property name="text">
|
||||
<string>Update period (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="updatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>Enter the time in seconds between each calculation of the target's position</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>3600.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
<string>Ground track points</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -418,6 +363,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="dateFormatLabel">
|
||||
<property name="text">
|
||||
<string>Date format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="dateFormat">
|
||||
<property name="toolTip">
|
||||
<string>Format for dates displayed in the GUI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="azElUnits">
|
||||
<property name="toolTip">
|
||||
@ -448,6 +407,48 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="defaultFrequency">
|
||||
<property name="toolTip">
|
||||
<string>Frequency used for Doppler and free space path loss calculations in the satellite table</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>50000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="updatePeriodLabel">
|
||||
<property name="text">
|
||||
<string>Update period (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="azElUnitsLabel">
|
||||
<property name="text">
|
||||
@ -455,27 +456,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QCheckBox" name="utc">
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="updatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>When checked times are dispayed using UTC rather than the local time zone</string>
|
||||
<string>Enter the time in seconds between each calculation of the target's position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display times in UTC</string>
|
||||
<property name="maximum">
|
||||
<double>3600.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="dateFormatLabel">
|
||||
<property name="text">
|
||||
<string>Date format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="groundTrackPointsLabel">
|
||||
<property name="text">
|
||||
<string>Ground track points</string>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -492,6 +482,45 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QCheckBox" name="drawOnMap">
|
||||
<property name="toolTip">
|
||||
<string>When checked satellite positions are sent to the map</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Draw satellites on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="drawRotators">
|
||||
<property name="toolTip">
|
||||
<string>Select which rotators are displayed on the polar chart</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Matching target</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="drawRotatorsLabel">
|
||||
<property name="text">
|
||||
<string>Rotators in polar chart</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="replayTab">
|
||||
@ -614,8 +643,8 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
<x>257</x>
|
||||
<y>533</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
@ -630,8 +659,8 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
<x>325</x>
|
||||
<y>533</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
|
@ -134,7 +134,7 @@ void getPassAzEl(QLineSeries* azimuth, QLineSeries* elevation, QLineSeries* pola
|
||||
DateTime aosTime = qDateTimeToDateTime(aos);
|
||||
DateTime losTime = qDateTimeToDateTime(los);
|
||||
DateTime currentTime(aosTime);
|
||||
int steps = 20;
|
||||
int steps = 150; // Needs to be high enough, so rotator intersect with satellite position
|
||||
|
||||
double timeStep = (losTime - aosTime).TotalSeconds() / steps;
|
||||
if (timeStep <= 0.0)
|
||||
|
@ -49,6 +49,8 @@ Pressing this button displays a settings dialog, that allows you to set:
|
||||
* The units to display the solar flux in, either Solar Flux Units, Jansky or Wm^-2Hz-1. 1 sfu equals 10,000 Jansky or 10^-22 Wm^-2Hz-1.
|
||||
* The update period in seconds, which controls how frequently azimuth and elevation are re-calculated.
|
||||
* The IP port number the Stellarium server listens on.
|
||||
* Which rotators are displayed on the polar chart. This can be All, None or Matching target. When Matching target is selected, the rotator will
|
||||
only be displayed if the source in the Rotator Controller is set to this Star Tracker and Track is enabled.
|
||||
* Whether to start a Stellarium telescope server.
|
||||
* Whether to draw the Sun in the map.
|
||||
* Whether to draw the Moon on the map.
|
||||
|
@ -33,8 +33,11 @@
|
||||
#include "SWGStarTrackerDisplaySettings.h"
|
||||
#include "SWGStarTrackerDisplayLoSSettings.h"
|
||||
|
||||
#include "feature/featureset.h"
|
||||
#include "feature/featureuiset.h"
|
||||
#include "feature/featureutils.h"
|
||||
#include "feature/featurewebapiutils.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "gui/basicfeaturesettingsdialog.h"
|
||||
#include "gui/dmsspinbox.h"
|
||||
#include "gui/graphicsviewzoom.h"
|
||||
@ -285,6 +288,8 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet,
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(1000);
|
||||
|
||||
connect(&m_redrawTimer, &QTimer::timeout, this, &StarTrackerGUI::plotChart);
|
||||
|
||||
connect(ui->azimuth, SIGNAL(valueChanged(double)), this, SLOT(on_azimuth_valueChanged(double)));
|
||||
ui->azimuth->setRange(0, 360.0);
|
||||
ui->elevation->setRange(-90.0, 90.0);
|
||||
@ -812,7 +817,7 @@ void StarTrackerGUI::on_displaySettings_clicked()
|
||||
ui->galacticLongitude->setUnits((DMSSpinBox::DisplayUnits)m_settings.m_azElUnits);
|
||||
displaySolarFlux();
|
||||
|
||||
if (ui->chartSelect->currentIndex() == 1) {
|
||||
if (ui->chartSelect->currentIndex() <= 1) {
|
||||
plotChart();
|
||||
}
|
||||
}
|
||||
@ -1651,6 +1656,26 @@ void StarTrackerGUI::plotElevationLineChart()
|
||||
delete oldChart;
|
||||
}
|
||||
|
||||
// Reduce az/el range from 450,180 to 360,90
|
||||
void StarTrackerGUI::limitAzElRange(double& azimuth, double& elevation) const
|
||||
{
|
||||
if (elevation > 90.0)
|
||||
{
|
||||
elevation = 180.0 - elevation;
|
||||
if (azimuth < 180.0) {
|
||||
azimuth += 180.0;
|
||||
} else {
|
||||
azimuth -= 180.0;
|
||||
}
|
||||
}
|
||||
if (azimuth > 360.0) {
|
||||
azimuth -= 360.0f;
|
||||
}
|
||||
if (azimuth == 0) {
|
||||
azimuth = 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Plot target elevation angle over the day
|
||||
void StarTrackerGUI::plotElevationPolarChart()
|
||||
{
|
||||
@ -1841,6 +1866,92 @@ void StarTrackerGUI::plotElevationPolarChart()
|
||||
series[i]->attachAxis(radialAxis);
|
||||
}
|
||||
|
||||
if (m_settings.m_drawRotators != StarTrackerSettings::NO_ROTATORS)
|
||||
{
|
||||
int redrawTime = 0;
|
||||
// Plot rotator position
|
||||
QString ourSourceName = QString("F0:%1 %2").arg(m_starTracker->getIndexInFeatureSet()).arg(m_starTracker->getIdentifier()); // Only one feature set in practice?
|
||||
std::vector<FeatureSet*>& featureSets = MainCore::instance()->getFeatureeSets();
|
||||
for (int featureSetIndex = 0; featureSetIndex < featureSets.size(); featureSetIndex++)
|
||||
{
|
||||
FeatureSet *featureSet = featureSets[featureSetIndex];
|
||||
for (int featureIndex = 0; featureIndex < featureSet->getNumberOfFeatures(); featureIndex++)
|
||||
{
|
||||
Feature *feature = featureSet->getFeatureAt(featureIndex);
|
||||
if (FeatureUtils::compareFeatureURIs(feature->getURI(), "sdrangel.feature.gs232controller"))
|
||||
{
|
||||
QString source;
|
||||
ChannelWebAPIUtils::getFeatureSetting(featureSetIndex, featureIndex, "source", source); // Will return false if source isn't set in Controller
|
||||
int track = 0;
|
||||
ChannelWebAPIUtils::getFeatureSetting(featureSetIndex, featureIndex, "track", track);
|
||||
if ((m_settings.m_drawRotators == StarTrackerSettings::ALL_ROTATORS) || ((source == ourSourceName) && track))
|
||||
{
|
||||
int onTarget = 0;
|
||||
ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "onTarget", onTarget);
|
||||
|
||||
if (!onTarget)
|
||||
{
|
||||
// Target azimuth red dotted line
|
||||
double targetAzimuth, targetElevation;
|
||||
bool targetAzimuthOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "targetAzimuth", targetAzimuth);
|
||||
bool targetElevationOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "targetElevation", targetElevation);
|
||||
if (targetAzimuthOk && targetElevationOk)
|
||||
{
|
||||
limitAzElRange(targetAzimuth, targetElevation);
|
||||
|
||||
QScatterSeries *rotatorSeries = new QScatterSeries();
|
||||
QColor color(255, 0, 0, 150);
|
||||
QPen pen(color);
|
||||
rotatorSeries->setPen(pen);
|
||||
rotatorSeries->setColor(color.darker());
|
||||
rotatorSeries->setMarkerSize(20);
|
||||
rotatorSeries->append(targetAzimuth, 90-targetElevation);
|
||||
m_azElPolarChart->addSeries(rotatorSeries);
|
||||
rotatorSeries->attachAxis(angularAxis);
|
||||
rotatorSeries->attachAxis(radialAxis);
|
||||
|
||||
redrawTime = 333;
|
||||
}
|
||||
}
|
||||
|
||||
// Current azimuth line. Yellow while off target, green on target.
|
||||
double currentAzimuth, currentElevation;
|
||||
bool currentAzimuthOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "currentAzimuth", currentAzimuth);
|
||||
bool currentElevationOk = ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "currentElevation", currentElevation);
|
||||
if (currentAzimuthOk && currentElevationOk)
|
||||
{
|
||||
limitAzElRange(currentAzimuth, currentElevation);
|
||||
|
||||
QScatterSeries *rotatorSeries = new QScatterSeries();
|
||||
QColor color;
|
||||
if (onTarget) {
|
||||
color = QColor(0, 255, 0, 150);
|
||||
} else {
|
||||
color = QColor(255, 255, 0, 150);
|
||||
}
|
||||
rotatorSeries->setPen(QPen(color));
|
||||
rotatorSeries->setColor(color.darker());
|
||||
rotatorSeries->setMarkerSize(20);
|
||||
rotatorSeries->append(currentAzimuth, 90-currentElevation);
|
||||
m_azElPolarChart->addSeries(rotatorSeries);
|
||||
rotatorSeries->attachAxis(angularAxis);
|
||||
rotatorSeries->attachAxis(radialAxis);
|
||||
|
||||
redrawTime = 333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (redrawTime > 0)
|
||||
{
|
||||
// Redraw to show updated rotator position
|
||||
// Update period may be long or custom time might be fixed
|
||||
m_redrawTimer.setSingleShot(true);
|
||||
m_redrawTimer.start(redrawTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Create series with single point, so we can plot time of rising
|
||||
if (riseTime.isValid())
|
||||
{
|
||||
@ -2242,3 +2353,4 @@ void StarTrackerGUI::makeUIConnections()
|
||||
QObject::connect(ui->drawSun, &QToolButton::clicked, this, &StarTrackerGUI::on_drawSun_clicked);
|
||||
QObject::connect(ui->drawMoon, &QToolButton::clicked, this, &StarTrackerGUI::on_drawMoon_clicked);
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,7 @@ private:
|
||||
|
||||
QChart *m_azElLineChart;
|
||||
QPolarChart *m_azElPolarChart;
|
||||
QTimer m_redrawTimer;
|
||||
|
||||
QChart m_chart;
|
||||
QDateTimeAxis m_chartXAxis;
|
||||
@ -161,6 +162,7 @@ private:
|
||||
void updateChartSubSelect();
|
||||
void updateSolarFlux(bool all);
|
||||
void makeUIConnections();
|
||||
void limitAzElRange(double& azimuth, double& elevation) const;
|
||||
|
||||
private slots:
|
||||
void onMenuDialogCalled(const QPoint &p);
|
||||
|
@ -83,6 +83,7 @@ void StarTrackerSettings::resetToDefaults()
|
||||
m_drawSunOnSkyTempChart = true;
|
||||
m_drawMoonOnSkyTempChart = true;
|
||||
m_workspaceIndex = 0;
|
||||
m_drawRotators = MATCHING_TARGET;
|
||||
}
|
||||
|
||||
QByteArray StarTrackerSettings::serialize() const
|
||||
@ -139,6 +140,7 @@ QByteArray StarTrackerSettings::serialize() const
|
||||
|
||||
s.writeS32(45, m_workspaceIndex);
|
||||
s.writeBlob(46, m_geometryBytes);
|
||||
s.writeS32(47, (int)m_drawRotators);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -227,6 +229,7 @@ bool StarTrackerSettings::deserialize(const QByteArray& data)
|
||||
|
||||
d.readS32(45, &m_workspaceIndex, 0);
|
||||
d.readBlob(46, &m_geometryBytes);
|
||||
d.readS32(47, (int *)&m_drawRotators, MATCHING_TARGET);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -374,6 +377,9 @@ void StarTrackerSettings::applySettings(const QStringList& settingsKeys, const S
|
||||
if (settingsKeys.contains("workspaceIndex")) {
|
||||
m_workspaceIndex = settings.m_workspaceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("drawRotators")) {
|
||||
m_drawRotators = settings.m_drawRotators;
|
||||
}
|
||||
}
|
||||
|
||||
QString StarTrackerSettings::getDebugString(const QStringList& settingsKeys, bool force) const
|
||||
@ -512,6 +518,9 @@ QString StarTrackerSettings::getDebugString(const QStringList& settingsKeys, boo
|
||||
if (settingsKeys.contains("workspaceIndex") || force) {
|
||||
ostr << " m_workspaceIndex: " << m_workspaceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("drawRotators") || force) {
|
||||
ostr << " m_drawRotators: " << m_drawRotators;
|
||||
}
|
||||
|
||||
return QString(ostr.str().c_str());
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ struct StarTrackerSettings
|
||||
Serializable *m_rollupState;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
enum Rotators {ALL_ROTATORS, NO_ROTATORS, MATCHING_TARGET} m_drawRotators; //!< Which rotators to draw on polar chart
|
||||
|
||||
StarTrackerSettings();
|
||||
void resetToDefaults();
|
||||
|
@ -44,8 +44,10 @@ StarTrackerSettingsDialog::StarTrackerSettingsDialog(
|
||||
ui->temperatureLapseRate->setValue(settings->m_temperatureLapseRate);
|
||||
ui->solarFluxData->setCurrentIndex((int)settings->m_solarFluxData);
|
||||
ui->solarFluxUnits->setCurrentIndex((int)settings->m_solarFluxUnits);
|
||||
ui->drawRotators->setCurrentIndex((int)settings->m_drawRotators);
|
||||
ui->drawSunOnMap->setChecked(settings->m_drawSunOnMap);
|
||||
ui->drawMoonOnMap->setChecked(settings->m_drawMoonOnMap);
|
||||
ui->drawStarOnMap->setChecked(settings->m_drawStarOnMap);
|
||||
}
|
||||
|
||||
StarTrackerSettingsDialog::~StarTrackerSettingsDialog()
|
||||
@ -70,6 +72,7 @@ void StarTrackerSettingsDialog::accept()
|
||||
m_settings->m_temperatureLapseRate = ui->temperatureLapseRate->value();
|
||||
m_settings->m_solarFluxData = (StarTrackerSettings::SolarFluxData)ui->solarFluxData->currentIndex();
|
||||
m_settings->m_solarFluxUnits = (StarTrackerSettings::SolarFluxUnits)ui->solarFluxUnits->currentIndex();
|
||||
m_settings->m_drawRotators = (StarTrackerSettings::Rotators)ui->drawRotators->currentIndex();
|
||||
m_settings->m_drawSunOnMap = ui->drawSunOnMap->isChecked();
|
||||
m_settings->m_drawMoonOnMap = ui->drawMoonOnMap->isChecked();
|
||||
m_settings->m_drawStarOnMap = ui->drawStarOnMap->isChecked();
|
||||
@ -89,6 +92,7 @@ void StarTrackerSettingsDialog::accept()
|
||||
m_settingsKeys.append("temperatureLapseRate");
|
||||
m_settingsKeys.append("solarFluxData");
|
||||
m_settingsKeys.append("solarFluxUnits");
|
||||
m_settingsKeys.append("drawRotators");
|
||||
m_settingsKeys.append("drawSunOnMap");
|
||||
m_settingsKeys.append("drawMoonOnMap");
|
||||
m_settingsKeys.append("drawStarOnMap");
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>569</width>
|
||||
<height>535</height>
|
||||
<height>556</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
@ -23,24 +23,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="epoch">
|
||||
<property name="toolTip">
|
||||
<string>Epoch for custom right ascension and declination</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>J2000</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>JNOW</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<item row="16" column="0">
|
||||
<widget class="QCheckBox" name="enableServer">
|
||||
<property name="toolTip">
|
||||
<string>Enable Stellarium server which allows RA and Dec to be sent to and from Stellarium</string>
|
||||
@ -50,74 +33,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="pressureLabel">
|
||||
<property name="text">
|
||||
<string>Air pressure (mb)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="humidity">
|
||||
<property name="toolTip">
|
||||
<string>Relative humidity in %</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>80</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="temperatureLapseRateLabel">
|
||||
<property name="toolTip">
|
||||
<string>Temperature lapse rate (K/m)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Temperature lapse rate (K/km)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QCheckBox" name="drawMoonOnMap">
|
||||
<property name="text">
|
||||
<string>Draw Moon on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QCheckBox" name="drawSunOnMap">
|
||||
<property name="text">
|
||||
<string>Draw Sun on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="temperatureLabel">
|
||||
<property name="text">
|
||||
<string>Air temperature (C)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="pressure">
|
||||
<property name="toolTip">
|
||||
<string>Air pressure in millibars, for use in atmospheric refraction correction</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1010.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="1">
|
||||
<item row="21" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -130,52 +46,13 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QCheckBox" name="drawStarOnMap">
|
||||
<item row="17" column="0">
|
||||
<widget class="QCheckBox" name="drawSunOnMap">
|
||||
<property name="text">
|
||||
<string>Draw target star on map</string>
|
||||
<string>Draw Sun on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="weatherUpdatePeriodLabel">
|
||||
<property name="text">
|
||||
<string>Weather update period (min)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="solarFluxDataLabel">
|
||||
<property name="text">
|
||||
<string>Solar flux density data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="refraction">
|
||||
<property name="toolTip">
|
||||
<string>Atmospheric refraction correction</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Saemundsson</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Positional Astronomy Library</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="azElUnits">
|
||||
<property name="toolTip">
|
||||
@ -206,153 +83,58 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="temperature">
|
||||
<property name="toolTip">
|
||||
<string>Air temperature in degrees Celsius, for use in atmospheric refraction correction</string>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="temperatureLabel">
|
||||
<property name="text">
|
||||
<string>Air temperature (C)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="humidity">
|
||||
<property name="toolTip">
|
||||
<string>Relative humidity in %</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
<number>80</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="solarFluxUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Solar flux density units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="temperatureLapseRate">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>6.490000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="refractionLabel">
|
||||
<property name="text">
|
||||
<string>Refraction correction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="solarFluxUnits">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="refraction">
|
||||
<property name="toolTip">
|
||||
<string>Units to use for the display of the Solar flux density</string>
|
||||
<string>Atmospheric refraction correction</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Solar flux units (sfu)</string>
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Jansky (Jy)</string>
|
||||
<string>Saemundsson</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Watts per square metre per hertz (W m^-2 Hz-1)</string>
|
||||
<string>Positional Astronomy Library</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="heightLabel">
|
||||
<property name="text">
|
||||
<string>Height above sea level (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="owmAPIKey">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="temperatureLapseRateLabel">
|
||||
<property name="toolTip">
|
||||
<string>API key from openweathermap.org to download real-time weather</string>
|
||||
<string>Temperature lapse rate (K/m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="serverPortLabel">
|
||||
<property name="text">
|
||||
<string>Stellarium server port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="epochLabel">
|
||||
<property name="text">
|
||||
<string>Epoch for RA & Dec</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="azElUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth and elevation units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="owmAPIKeyLabel">
|
||||
<property name="text">
|
||||
<string>OpenWeatherMap API Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="serverPort">
|
||||
<property name="toolTip">
|
||||
<string>Stellarium telescope server IP port number</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10001</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QDoubleSpinBox" name="updatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>Enter the time in seconds between each calculation of the target's position</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="updatePeriodLabel">
|
||||
<property name="text">
|
||||
<string>Update period (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="weatherUpdatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>Enter the time in minutes between each weather update</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
<string>Temperature lapse rate (K/km)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -363,16 +145,68 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="height">
|
||||
<property name="toolTip">
|
||||
<string>Height of observation/antenna location above sea level in metres</string>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="epochLabel">
|
||||
<property name="text">
|
||||
<string>Epoch for RA & Dec</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1000</number>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="weatherUpdatePeriodLabel">
|
||||
<property name="text">
|
||||
<string>Weather update period (min)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="pressureLabel">
|
||||
<property name="text">
|
||||
<string>Air pressure (mb)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="0">
|
||||
<widget class="QCheckBox" name="drawStarOnMap">
|
||||
<property name="text">
|
||||
<string>Draw target star on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="owmAPIKeyLabel">
|
||||
<property name="text">
|
||||
<string>OpenWeatherMap API Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="solarFluxUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Solar flux density units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="pressure">
|
||||
<property name="toolTip">
|
||||
<string>Air pressure in millibars, for use in atmospheric refraction correction</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>20000</number>
|
||||
<double>2000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1010.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="heightLabel">
|
||||
<property name="text">
|
||||
<string>Height above sea level (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -433,6 +267,201 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="temperatureLapseRate">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>6.490000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="owmAPIKey">
|
||||
<property name="toolTip">
|
||||
<string>API key from openweathermap.org to download real-time weather</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="temperature">
|
||||
<property name="toolTip">
|
||||
<string>Air temperature in degrees Celsius, for use in atmospheric refraction correction</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QCheckBox" name="drawMoonOnMap">
|
||||
<property name="text">
|
||||
<string>Draw Moon on map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="updatePeriodLabel">
|
||||
<property name="text">
|
||||
<string>Update period (s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="epoch">
|
||||
<property name="toolTip">
|
||||
<string>Epoch for custom right ascension and declination</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>J2000</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>JNOW</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="refractionLabel">
|
||||
<property name="text">
|
||||
<string>Refraction correction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="solarFluxDataLabel">
|
||||
<property name="text">
|
||||
<string>Solar flux density data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="solarFluxUnits">
|
||||
<property name="toolTip">
|
||||
<string>Units to use for the display of the Solar flux density</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Solar flux units (sfu)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Jansky (Jy)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Watts per square metre per hertz (W m^-2 Hz-1)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="height">
|
||||
<property name="toolTip">
|
||||
<string>Height of observation/antenna location above sea level in metres</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>20000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QDoubleSpinBox" name="updatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>Enter the time in seconds between each calculation of the target's position</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="serverPort">
|
||||
<property name="toolTip">
|
||||
<string>Stellarium telescope server IP port number</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10001</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="serverPortLabel">
|
||||
<property name="text">
|
||||
<string>Stellarium server port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="weatherUpdatePeriod">
|
||||
<property name="toolTip">
|
||||
<string>Enter the time in minutes between each weather update</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="azElUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth and elevation units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="drawRotatorsLabel">
|
||||
<property name="text">
|
||||
<string>Rotators in polar chart</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QComboBox" name="drawRotators">
|
||||
<property name="toolTip">
|
||||
<string>Select which rotators are displayed on the polar chart</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Matching target</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "maincore.h"
|
||||
#include "device/deviceset.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "channel/channelutils.h"
|
||||
#include "dsp/devicesamplesource.h"
|
||||
#include "dsp/devicesamplesink.h"
|
||||
@ -219,7 +220,83 @@ bool ChannelWebAPIUtils::getFeatureReport(unsigned int featureSetIndex, unsigned
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getFeatureReport: get feature settings error %d: %s",
|
||||
qWarning("ChannelWebAPIUtils::getFeatureReport: get feature report error %d: %s",
|
||||
httpRC, qPrintable(errorResponse));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelSettings(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelSettings &channelSettingsResponse, ChannelAPI *&channel)
|
||||
{
|
||||
QString errorResponse;
|
||||
int httpRC;
|
||||
DeviceSet *deviceSet;
|
||||
|
||||
// Get current channel settings
|
||||
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
|
||||
if (deviceIndex < deviceSets.size())
|
||||
{
|
||||
deviceSet = deviceSets[deviceIndex];
|
||||
if (channelIndex < (unsigned int) deviceSet->getNumberOfChannels())
|
||||
{
|
||||
channel = deviceSet->getChannelAt(channelIndex);
|
||||
httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ChannelWebAPIUtils::getChannelSettings: no channel " << deviceIndex << ":" << channelIndex;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ChannelWebAPIUtils::getChannelSettings: no device " << deviceIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getChannelSettings: get channel settings error %d: %s",
|
||||
httpRC, qPrintable(errorResponse));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelReport(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelReport &channelReport)
|
||||
{
|
||||
QString errorResponse;
|
||||
int httpRC;
|
||||
DeviceSet *deviceSet;
|
||||
|
||||
// Get channel report
|
||||
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
|
||||
if (deviceIndex < deviceSets.size())
|
||||
{
|
||||
deviceSet = deviceSets[deviceIndex];
|
||||
if (channelIndex < (unsigned int) deviceSet->getNumberOfChannels())
|
||||
{
|
||||
ChannelAPI *channel = deviceSet->getChannelAt(channelIndex);
|
||||
httpRC = channel->webapiReportGet(channelReport, errorResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ChannelWebAPIUtils::getChannelReport: no channel " << deviceIndex << ":" << channelIndex;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ChannelWebAPIUtils::getChannelReport: no device set " << deviceIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (httpRC/100 != 2)
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getChannelReport: get channel report error %d: %s",
|
||||
httpRC, qPrintable(errorResponse));
|
||||
return false;
|
||||
}
|
||||
@ -1193,6 +1270,22 @@ bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsign
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double &value)
|
||||
{
|
||||
SWGSDRangel::SWGFeatureSettings featureSettingsResponse;
|
||||
Feature *feature;
|
||||
|
||||
if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature))
|
||||
{
|
||||
QJsonObject *jsonObj = featureSettingsResponse.asJsonObject();
|
||||
return WebAPIUtils::getSubObjectDouble(*jsonObj, setting, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, QString &value)
|
||||
{
|
||||
SWGSDRangel::SWGFeatureSettings featureSettingsResponse;
|
||||
@ -1209,6 +1302,54 @@ bool ChannelWebAPIUtils::getFeatureSetting(unsigned int featureSetIndex, unsign
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, int &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||
ChannelAPI *channel;
|
||||
|
||||
if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel))
|
||||
{
|
||||
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||
return WebAPIUtils::getSubObjectInt(*jsonObj, setting, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, double &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||
ChannelAPI *channel;
|
||||
|
||||
if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel))
|
||||
{
|
||||
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||
return WebAPIUtils::getSubObjectDouble(*jsonObj, setting, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, QString &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||
ChannelAPI *channel;
|
||||
|
||||
if (getChannelSettings(deviceSetIndex, channelIndex, channelSettingsResponse, channel))
|
||||
{
|
||||
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||
return WebAPIUtils::getSubObjectString(*jsonObj, setting, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, int &value)
|
||||
{
|
||||
SWGSDRangel::SWGFeatureReport featureReport;
|
||||
@ -1231,6 +1372,28 @@ bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, uns
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, double &value)
|
||||
{
|
||||
SWGSDRangel::SWGFeatureReport featureReport;
|
||||
|
||||
if (getFeatureReport(featureSetIndex, featureIndex, featureReport))
|
||||
{
|
||||
// Get value of requested key
|
||||
QJsonObject *jsonObj = featureReport.asJsonObject();
|
||||
if (WebAPIUtils::getSubObjectDouble(*jsonObj, key, value))
|
||||
{
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getFeatureReportValue: no key %s in feature report", qPrintable(key));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, QString &value)
|
||||
{
|
||||
SWGSDRangel::SWGFeatureReport featureReport;
|
||||
@ -1252,3 +1415,71 @@ bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, uns
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, int &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelReport channelReport;
|
||||
|
||||
if (getChannelReport(deviceIndex, channelIndex, channelReport))
|
||||
{
|
||||
// Get value of requested key
|
||||
QJsonObject *jsonObj = channelReport.asJsonObject();
|
||||
if (WebAPIUtils::getSubObjectInt(*jsonObj, key, value))
|
||||
{
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, double &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelReport channelReport;
|
||||
|
||||
if (getChannelReport(deviceIndex, channelIndex, channelReport))
|
||||
{
|
||||
// Get value of requested key
|
||||
QJsonObject *jsonObj = channelReport.asJsonObject();
|
||||
if (WebAPIUtils::getSubObjectDouble(*jsonObj, key, value))
|
||||
{
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelWebAPIUtils::getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, QString &value)
|
||||
{
|
||||
SWGSDRangel::SWGChannelReport channelReport;
|
||||
|
||||
if (getChannelReport(deviceIndex, channelIndex, channelReport))
|
||||
{
|
||||
// Get value of requested key
|
||||
QJsonObject *jsonObj = channelReport.asJsonObject();
|
||||
if (WebAPIUtils::getSubObjectString(*jsonObj, key, value))
|
||||
{
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("ChannelWebAPIUtils::getChannelReportValue: no key %s in channel report", qPrintable(key));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,14 @@
|
||||
#include "SWGDeviceReport.h"
|
||||
#include "SWGFeatureSettings.h"
|
||||
#include "SWGFeatureReport.h"
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGChannelReport.h"
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class DeviceSet;
|
||||
class Feature;
|
||||
class ChannelAPI;
|
||||
|
||||
class SDRBASE_API ChannelWebAPIUtils
|
||||
{
|
||||
@ -67,15 +70,26 @@ public:
|
||||
static bool patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value);
|
||||
static bool patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double value);
|
||||
static bool getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, int &value);
|
||||
static bool getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double &value);
|
||||
static bool getFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, QString &value);
|
||||
static bool getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, int &value);
|
||||
static bool getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, double &value);
|
||||
static bool getChannelSetting(unsigned int deviceSetIndex, unsigned int channelIndex, const QString &setting, QString &value);
|
||||
static bool getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, int &value);
|
||||
static bool getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, double &value);
|
||||
static bool getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, QString &value);
|
||||
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, int &value);
|
||||
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, double &value);
|
||||
static bool getChannelReportValue(unsigned int deviceIndex, unsigned int channelIndex, const QString &key, QString &value);
|
||||
protected:
|
||||
static bool getDeviceSettings(unsigned int deviceIndex, SWGSDRangel::SWGDeviceSettings &deviceSettingsResponse, DeviceSet *&deviceSet);
|
||||
static bool getDeviceReport(unsigned int deviceIndex, SWGSDRangel::SWGDeviceReport &deviceReport);
|
||||
static bool getFeatureSettings(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureSettings &featureSettingsResponse, Feature *&feature);
|
||||
static bool getFeatureReport(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureReport &featureReport);
|
||||
static bool getChannelSettings(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelSettings &channelSettingsResponse, ChannelAPI *&channel);
|
||||
static bool getChannelReport(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelReport &channelReport);
|
||||
static QString getDeviceHardwareId(unsigned int deviceIndex);
|
||||
};
|
||||
|
||||
#endif // SDRBASE_CHANNEL_CHANNELWEBAPIUTILS_H_
|
||||
|
||||
|
@ -286,6 +286,183 @@ RADec Astronomy::azAltToRaDec(AzAlt aa, double latitude, double longitude, QDate
|
||||
return rd;
|
||||
}
|
||||
|
||||
// https://ntrs.nasa.gov/api/citations/19670030005/downloads/19670030005.pdf
|
||||
// X85 is positive Southward
|
||||
// Y85 is positive Eastward
|
||||
// X30 is positive Eastward
|
||||
// Y30 is positive Northward
|
||||
// atan2 range is (-pi,pi], we want az (0,360], so need to add pi
|
||||
void Astronomy::azAltToXY85(AzAlt aa, double& x, double& y)
|
||||
{
|
||||
if (aa.alt == 90.0)
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
//qDebug() << "azAltToXY85" << aa.az << aa.alt << x << y;
|
||||
return;
|
||||
}
|
||||
double az = aa.az;
|
||||
double el = aa.alt;
|
||||
if (az >= 360.0) {
|
||||
az -= 360.0;
|
||||
}
|
||||
if (el > 90.0)
|
||||
{
|
||||
el = 180.0 - el;
|
||||
if (az >= 180.0) {
|
||||
az = az - 180.0;
|
||||
} else {
|
||||
az = az + 180.0;
|
||||
}
|
||||
}
|
||||
double azr = Units::degreesToRadians(az);
|
||||
double elr = Units::degreesToRadians(el);
|
||||
y = Units::radiansToDegrees(asin(cos(elr) * sin(azr)));
|
||||
if (az == 0.0)
|
||||
{
|
||||
// cot(0) == Inf
|
||||
if ((az == 90.0) || (az == 270.0)) {
|
||||
x = 0.0;
|
||||
} else if ((az > 90.0f) && (az < 270.0)) {
|
||||
x = 90.0;
|
||||
} else {
|
||||
x = -90.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// cot(x)=1/tan(x)=cos(x)/sin(x)
|
||||
x = Units::radiansToDegrees(atan(-(cos(elr)/sin(elr)) * cos(azr)));
|
||||
}
|
||||
|
||||
//qDebug() << "azAltToXY85" << aa.az << aa.alt << x << y;
|
||||
}
|
||||
|
||||
void Astronomy::azAltToXY30(AzAlt aa, double& x, double& y)
|
||||
{
|
||||
if (aa.alt == 90.0)
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
//qDebug() << "azAltToXY30" << aa.az << aa.alt << x << y;
|
||||
return;
|
||||
}
|
||||
double az = aa.az;
|
||||
double el = aa.alt;
|
||||
if (az >= 360.0) {
|
||||
az -= 360.0;
|
||||
}
|
||||
if (el > 90.0)
|
||||
{
|
||||
el = 180.0 - el;
|
||||
if (az >= 180.0) {
|
||||
az = az - 180.0;
|
||||
} else {
|
||||
az = az + 180.0;
|
||||
}
|
||||
}
|
||||
double azr = Units::degreesToRadians(az);
|
||||
double elr = Units::degreesToRadians(el);
|
||||
y = Units::radiansToDegrees(asin(cos(elr) * cos(azr)));
|
||||
if (el == 0.0)
|
||||
{
|
||||
if ((az == 0.0) || (az == 180.0)) {
|
||||
x = 0.0;
|
||||
} else if ((az >= 0.0f) && (az <= 180.0)) {
|
||||
x = 90.0;
|
||||
} else {
|
||||
x = -90.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = Units::radiansToDegrees(atan((cos(elr)/sin(elr)) * sin(azr)));
|
||||
}
|
||||
//qDebug() << "azAltToXY30" << aa.az << aa.alt << x << y;
|
||||
}
|
||||
|
||||
AzAlt Astronomy::xy85ToAzAlt(double x, double y)
|
||||
{
|
||||
AzAlt aa;
|
||||
if ((x == 0.0) && (y == 0.0))
|
||||
{
|
||||
aa.az = 0.0;
|
||||
aa.alt = 90.0;
|
||||
//qDebug() << "xy85ToAzAlt" << x << y << aa.az << aa.alt;
|
||||
return aa;
|
||||
}
|
||||
double xr = Units::degreesToRadians(x);
|
||||
double yr = Units::degreesToRadians(y);
|
||||
double elr = asin(cos(yr) * cos(xr));
|
||||
double azr;
|
||||
if (x == 0.0)
|
||||
{
|
||||
// 1/sin(x) == Inf
|
||||
azr = y >= 0.0 ? M_PI/2.0 : 2.0*M_PI*3.0/4.0;
|
||||
}
|
||||
else if (y == 90.0)
|
||||
{
|
||||
// tan(90) == Inf
|
||||
azr = M_PI/2.0;
|
||||
}
|
||||
else if (y == -90.0)
|
||||
{
|
||||
// tan(-90) == Inf
|
||||
azr = 2.0*M_PI*3.0/4.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// atan2(y,x) = atan(y/x)
|
||||
azr = atan2(-tan(yr), sin(xr)) + M_PI;
|
||||
}
|
||||
aa.az = Units::radiansToDegrees(azr);
|
||||
aa.alt = Units::radiansToDegrees(elr);
|
||||
//qDebug() << "xy85ToAzAlt" << x << y << aa.az << aa.alt;
|
||||
return aa;
|
||||
}
|
||||
|
||||
AzAlt Astronomy::xy30ToAzAlt(double x, double y)
|
||||
{
|
||||
AzAlt aa;
|
||||
if ((x == 0.0) && (y == 0.0))
|
||||
{
|
||||
aa.az = 0.0;
|
||||
aa.alt = 90.0;
|
||||
//qDebug() << "xy30ToAzAlt" << x << y << aa.az << aa.alt;
|
||||
return aa;
|
||||
}
|
||||
double xr = Units::degreesToRadians(x);
|
||||
double yr = Units::degreesToRadians(y);
|
||||
double elr = asin(cos(yr) * cos(xr));
|
||||
double azr;
|
||||
if (y == 0.0)
|
||||
{
|
||||
// cot(0) == Inf
|
||||
azr = x >= 0.0 ? M_PI/2.0 : 2.0*M_PI*3.0/4.0;
|
||||
}
|
||||
else if (y == 90.0)
|
||||
{
|
||||
// tan(90) == Inf
|
||||
azr = 0.0;
|
||||
}
|
||||
else if (y == -90.0)
|
||||
{
|
||||
// tan(-90) == Inf
|
||||
azr = M_PI;
|
||||
}
|
||||
else
|
||||
{
|
||||
azr = atan2(sin(xr), tan(yr));
|
||||
if (azr < 0.0) {
|
||||
azr += 2.0*M_PI;
|
||||
}
|
||||
}
|
||||
aa.az = Units::radiansToDegrees(azr);
|
||||
aa.alt = Units::radiansToDegrees(elr);
|
||||
//qDebug() << "xy30ToAzAlt" << x << y << aa.az << aa.alt;
|
||||
return aa;
|
||||
}
|
||||
|
||||
// Needs to work for negative a
|
||||
double Astronomy::modulo(double a, double b)
|
||||
{
|
||||
@ -3707,3 +3884,4 @@ static int eraEpv00(double date1, double date2,
|
||||
/* Finished. */
|
||||
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,11 @@ public:
|
||||
static AzAlt raDecToAzAlt(RADec rd, double latitude, double longitude, QDateTime dt, bool j2000=true);
|
||||
static RADec azAltToRaDec(AzAlt aa, double latitude, double longitude, QDateTime dt);
|
||||
|
||||
static void azAltToXY85(AzAlt aa, double& x, double& y);
|
||||
static void azAltToXY30(AzAlt aa, double& x, double& y);
|
||||
static AzAlt xy85ToAzAlt(double x, double y);
|
||||
static AzAlt xy30ToAzAlt(double x, double y);
|
||||
|
||||
static double localSiderealTime(QDateTime dateTime, double longitude);
|
||||
|
||||
static void sunPosition(AzAlt& aa, RADec& rd, double latitude, double longitude, QDateTime dt);
|
||||
|
@ -15,6 +15,8 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "coursedeviationindicator.h"
|
||||
@ -46,6 +48,8 @@ void CourseDeviationIndicator::setGlideSlopeDDM(float ddm)
|
||||
|
||||
void CourseDeviationIndicator::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
(void) event;
|
||||
|
||||
QPainter painter(this);
|
||||
|
||||
QRect r = rect();
|
||||
@ -168,7 +172,6 @@ void CourseDeviationIndicator::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QFontMetrics fm(painter.font());
|
||||
QString text = "G/S";
|
||||
int tw = fm.horizontalAdvance(text);
|
||||
int th = fm.ascent() / 2;
|
||||
painter.setPen(QColor(0, 255, 0));
|
||||
painter.drawText(midW + bgw + 2, midH + th, text);
|
||||
|
@ -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
|
||||
|
@ -60,6 +60,10 @@ SWGGS232ControllerSettings::SWGGS232ControllerSettings() {
|
||||
m_tolerance_isSet = false;
|
||||
protocol = 0;
|
||||
m_protocol_isSet = false;
|
||||
precision = 0;
|
||||
m_precision_isSet = false;
|
||||
coordinates = 0;
|
||||
m_coordinates_isSet = false;
|
||||
title = nullptr;
|
||||
m_title_isSet = false;
|
||||
rgb_color = 0;
|
||||
@ -116,6 +120,10 @@ SWGGS232ControllerSettings::init() {
|
||||
m_tolerance_isSet = false;
|
||||
protocol = 0;
|
||||
m_protocol_isSet = false;
|
||||
precision = 0;
|
||||
m_precision_isSet = false;
|
||||
coordinates = 0;
|
||||
m_coordinates_isSet = false;
|
||||
title = new QString("");
|
||||
m_title_isSet = false;
|
||||
rgb_color = 0;
|
||||
@ -158,6 +166,8 @@ SWGGS232ControllerSettings::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
@ -217,6 +227,10 @@ SWGGS232ControllerSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&protocol, pJson["protocol"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&precision, pJson["precision"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&coordinates, pJson["coordinates"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
@ -297,6 +311,12 @@ SWGGS232ControllerSettings::asJsonObject() {
|
||||
if(m_protocol_isSet){
|
||||
obj->insert("protocol", QJsonValue(protocol));
|
||||
}
|
||||
if(m_precision_isSet){
|
||||
obj->insert("precision", QJsonValue(precision));
|
||||
}
|
||||
if(m_coordinates_isSet){
|
||||
obj->insert("coordinates", QJsonValue(coordinates));
|
||||
}
|
||||
if(title != nullptr && *title != QString("")){
|
||||
toJsonValue(QString("title"), title, obj, QString("QString"));
|
||||
}
|
||||
@ -485,6 +505,26 @@ SWGGS232ControllerSettings::setProtocol(qint32 protocol) {
|
||||
this->m_protocol_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGGS232ControllerSettings::getPrecision() {
|
||||
return precision;
|
||||
}
|
||||
void
|
||||
SWGGS232ControllerSettings::setPrecision(qint32 precision) {
|
||||
this->precision = precision;
|
||||
this->m_precision_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGGS232ControllerSettings::getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
void
|
||||
SWGGS232ControllerSettings::setCoordinates(qint32 coordinates) {
|
||||
this->coordinates = coordinates;
|
||||
this->m_coordinates_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGGS232ControllerSettings::getTitle() {
|
||||
return title;
|
||||
@ -618,6 +658,12 @@ SWGGS232ControllerSettings::isSet(){
|
||||
if(m_protocol_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_precision_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_coordinates_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(title && *title != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -91,6 +91,12 @@ public:
|
||||
qint32 getProtocol();
|
||||
void setProtocol(qint32 protocol);
|
||||
|
||||
qint32 getPrecision();
|
||||
void setPrecision(qint32 precision);
|
||||
|
||||
qint32 getCoordinates();
|
||||
void setCoordinates(qint32 coordinates);
|
||||
|
||||
QString* getTitle();
|
||||
void setTitle(QString* title);
|
||||
|
||||
@ -167,6 +173,12 @@ private:
|
||||
qint32 protocol;
|
||||
bool m_protocol_isSet;
|
||||
|
||||
qint32 precision;
|
||||
bool m_precision_isSet;
|
||||
|
||||
qint32 coordinates;
|
||||
bool m_coordinates_isSet;
|
||||
|
||||
QString* title;
|
||||
bool m_title_isSet;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user