diff --git a/CMakeLists.txt b/CMakeLists.txt index 98a73cb08..d20a95429 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ option(ENABLE_FEATURE_RIGCTLSERVER "Enable feature rigctlserver plugin" ON) option(ENABLE_FEATURE_PERTESTER "Enable feature pertester plugin" ON) option(ENABLE_FEATURE_GS232CONTROLLER "Enable feature gs232controller plugin" ON) option(ENABLE_FEATURE_REMOTECONTROL "Enable feature remote control plugin" ON) +option(ENABLE_FEATURE_SKYMAP "Enable feature sky map plugin" ON) # on windows always build external libraries if(WIN32) diff --git a/doc/img/SkyMap_ESASky.png b/doc/img/SkyMap_ESASky.png new file mode 100644 index 000000000..1fcedf063 Binary files /dev/null and b/doc/img/SkyMap_ESASky.png differ diff --git a/doc/img/SkyMap_settings.png b/doc/img/SkyMap_settings.png new file mode 100644 index 000000000..ff005222e Binary files /dev/null and b/doc/img/SkyMap_settings.png differ diff --git a/doc/img/SkyMap_wwt.png b/doc/img/SkyMap_wwt.png new file mode 100644 index 000000000..d52549a3f Binary files /dev/null and b/doc/img/SkyMap_wwt.png differ diff --git a/plugins/channelrx/freqscanner/freqscanner.cpp b/plugins/channelrx/freqscanner/freqscanner.cpp index 653f2cc4a..6d4c3c509 100644 --- a/plugins/channelrx/freqscanner/freqscanner.cpp +++ b/plugins/channelrx/freqscanner/freqscanner.cpp @@ -67,6 +67,7 @@ FreqScanner::FreqScanner(DeviceAPI *deviceAPI) : m_basebandSink(nullptr), m_running(false), m_basebandSampleRate(0), + m_availableChannelHandler({}), m_scanDeviceSetIndex(0), m_scanChannelIndex(0), m_state(IDLE), @@ -95,19 +96,8 @@ FreqScanner::FreqScanner(DeviceAPI *deviceAPI) : start(); - scanAvailableChannels(); - QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, - this, - &FreqScanner::handleChannelAdded - ); - QObject::connect( - MainCore::instance(), - &MainCore::channelRemoved, - this, - &FreqScanner::handleChannelRemoved - ); + QObject::connect(&m_availableChannelHandler, &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, &FreqScanner::channelsChanged); + m_availableChannelHandler.scanAvailableChannelsAndFeatures(); m_timeoutTimer.callOnTimeout(this, &FreqScanner::timeout); } @@ -708,7 +698,7 @@ void FreqScanner::applySettings(const FreqScannerSettings& settings, const QStri m_deviceAPI->removeChannelSink(this, m_settings.m_streamIndex); m_deviceAPI->addChannelSink(this, settings.m_streamIndex); m_deviceAPI->addChannelSinkAPI(this); - scanAvailableChannels(); // re-scan + //FIXME:scanAvailableChannels(); // re-scan emit streamIndexChanged(settings.m_streamIndex); } } @@ -1116,186 +1106,18 @@ void FreqScanner::handleIndexInDeviceSetChanged(int index) m_basebandSink->setFifoLabel(fifoLabel); } -void FreqScanner::scanAvailableChannels() +void FreqScanner::channelsChanged(const QStringList& renameFrom, const QStringList& renameTo) { - m_availableChannels.clear(); - - DSPDeviceSourceEngine* deviceSourceEngine = getDeviceAPI()->getDeviceSourceEngine(); - - if (deviceSourceEngine) - { - for (int chi = 0; chi < getDeviceAPI()->getNbSinkChannels(); chi++) // Rx channels - { - ChannelAPI* channel = getDeviceAPI()->getChanelSinkAPIAt(chi); - - if (channel->getIndexInDeviceSet() == getIndexInDeviceSet()) { // Exclude oneself - continue; - } - - FreqScannerSettings::AvailableChannel availableChannel = - FreqScannerSettings::AvailableChannel{ - channel->getDeviceSetIndex(), - channel->getIndexInDeviceSet(), - -1 - }; - m_availableChannels[channel] = availableChannel; - QObject::connect( - channel, - &ChannelAPI::streamIndexChanged, - [=](int streamIndex){ - this->handleChannelStreamIndexChanged(streamIndex, channel); - } - ); - } - } - - DSPDeviceMIMOEngine *deviceMIMOEngine = getDeviceAPI()->getDeviceMIMOEngine(); - - if (deviceMIMOEngine) - { - for (int chi = 0; chi < getDeviceAPI()->getNbSinkChannels(); chi++) // Rx channels - { - ChannelAPI* channel = getDeviceAPI()->getChanelSinkAPIAt(chi); - - if (channel->getIndexInDeviceSet() == getIndexInDeviceSet()) { // Exclude oneself - continue; - } - - // Single Rx on the same I/Q stream - if ((channel->getNbSinkStreams() == 1) - && (channel->getNbSourceStreams() == 0) - && (channel->getStreamIndex() == m_settings.m_streamIndex)) - { - FreqScannerSettings::AvailableChannel availableChannel = - FreqScannerSettings::AvailableChannel{ - channel->getDeviceSetIndex(), - channel->getIndexInDeviceSet(), - channel->getStreamIndex() - }; - m_availableChannels[channel] = availableChannel; - QObject::connect( - channel, - &ChannelAPI::streamIndexChanged, - [=](int streamIndex){ - this->handleChannelStreamIndexChanged(streamIndex, channel); - } - ); - } - } - } - - notifyUpdateChannels(); + m_availableChannels = m_availableChannelHandler.getAvailableChannelOrFeatureList(); + notifyUpdateChannels(renameFrom, renameTo); } -void FreqScanner::handleChannelAdded(int deviceSetIndex, ChannelAPI* channel) -{ - if (deviceSetIndex != getDeviceSetIndex()) { // Can control channels only in the same device set - return; - } - - qDebug("FreqScanner::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - DSPDeviceSourceEngine* deviceSourceEngine = getDeviceAPI()->getDeviceSourceEngine(); - - if (deviceSourceEngine) - { - FreqScannerSettings::AvailableChannel availableChannel = - FreqScannerSettings::AvailableChannel{ deviceSetIndex, channel->getIndexInDeviceSet(), -1}; - m_availableChannels[channel] = availableChannel; - QObject::connect( - channel, - &ChannelAPI::streamIndexChanged, - [=](int streamIndex){ - this->handleChannelStreamIndexChanged(streamIndex, channel); - } - ); - } - - DSPDeviceMIMOEngine *deviceMIMOEngine = getDeviceAPI()->getDeviceMIMOEngine(); - - if (deviceMIMOEngine - && (channel->getNbSinkStreams() == 1) - && (channel->getNbSourceStreams() == 0) - && (channel->getStreamIndex() == m_settings.m_streamIndex)) - { - FreqScannerSettings::AvailableChannel availableChannel = - FreqScannerSettings::AvailableChannel{ - deviceSetIndex, - channel->getIndexInDeviceSet(), - channel->getStreamIndex() - }; - m_availableChannels[channel] = availableChannel; - QObject::connect( - channel, - &ChannelAPI::streamIndexChanged, - [=](int streamIndex){ - this->handleChannelStreamIndexChanged(streamIndex, channel); - } - ); - } - - notifyUpdateChannels(); -} - -void FreqScanner::handleChannelRemoved(int deviceSetIndex, ChannelAPI* channel) -{ - if (deviceSetIndex != getDeviceSetIndex()) { // Can control channels only in the same device set - return; - } - - qDebug("FreqScanner::handleChannelRemoved: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - DSPDeviceSourceEngine* deviceSourceEngine = getDeviceAPI()->getDeviceSourceEngine(); - DSPDeviceMIMOEngine *deviceMIMOEngine = getDeviceAPI()->getDeviceMIMOEngine(); - - if (deviceSourceEngine || deviceMIMOEngine) { - m_availableChannels.remove(channel); - } - - notifyUpdateChannels(); -} - -void FreqScanner::handleChannelStreamIndexChanged(int streamIndex, ChannelAPI* channel) -{ - qDebug("FreqScanner::handleChannelStreamIndexChanged: channel: %s (%p) stream: %d", - qPrintable(channel->getURI()), channel, streamIndex); - if (streamIndex != m_settings.m_streamIndex) // channel has moved to another I/Q stream - { - m_availableChannels.remove(channel); - notifyUpdateChannels(); - } - else if (!m_availableChannels.contains(channel)) // if channel has been tracked before put back it in the list - { - FreqScannerSettings::AvailableChannel availableChannel = - FreqScannerSettings::AvailableChannel{ - getDeviceSetIndex(), - channel->getIndexInDeviceSet(), - channel->getStreamIndex() - }; - m_availableChannels[channel] = availableChannel; - notifyUpdateChannels(); - } -} - -void FreqScanner::notifyUpdateChannels() +void FreqScanner::notifyUpdateChannels(const QStringList& renameFrom, const QStringList& renameTo) { if (getMessageQueueToGUI()) { - MsgReportChannels* msgToGUI = MsgReportChannels::create(); - QList& msgChannels = msgToGUI->getChannels(); - QHash::iterator it = m_availableChannels.begin(); - - for (; it != m_availableChannels.end(); ++it) - { - FreqScannerSettings::AvailableChannel msgChannel = - FreqScannerSettings::AvailableChannel{ - it->m_deviceSetIndex, - it->m_channelIndex, - it->m_streamIndex - }; - msgChannels.push_back(msgChannel); - } - + MsgReportChannels* msgToGUI = MsgReportChannels::create(renameFrom, renameTo); + msgToGUI->getChannels() = m_availableChannels; getMessageQueueToGUI()->push(msgToGUI); } } diff --git a/plugins/channelrx/freqscanner/freqscanner.h b/plugins/channelrx/freqscanner/freqscanner.h index 09a52c946..40f1fc84d 100644 --- a/plugins/channelrx/freqscanner/freqscanner.h +++ b/plugins/channelrx/freqscanner/freqscanner.h @@ -27,6 +27,7 @@ #include "dsp/basebandsamplesink.h" #include "channel/channelapi.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" #include "freqscannerbaseband.h" #include "freqscannersettings.h" @@ -71,17 +72,23 @@ public: public: - QList& getChannels() { return m_channels; } + AvailableChannelOrFeatureList& getChannels() { return m_channels; } + const QStringList& getRenameFrom() const { return m_renameFrom; } + const QStringList& getRenameTo() const { return m_renameTo; } - static MsgReportChannels* create() { - return new MsgReportChannels(); + static MsgReportChannels* create(const QStringList& renameFrom, const QStringList& renameTo) { + return new MsgReportChannels(renameFrom, renameTo); } private: - QList m_channels; + AvailableChannelOrFeatureList m_channels; + QStringList m_renameFrom; + QStringList m_renameTo; - MsgReportChannels() : - Message() + MsgReportChannels(const QStringList& renameFrom, const QStringList& renameTo) : + Message(), + m_renameFrom(renameFrom), + m_renameTo(renameTo) {} }; @@ -369,7 +376,8 @@ private: QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; - QHash m_availableChannels; + AvailableChannelOrFeatureList m_availableChannels; + AvailableChannelOrFeatureHandler m_availableChannelHandler; unsigned int m_scanDeviceSetIndex; unsigned int m_scanChannelIndex; @@ -402,8 +410,8 @@ private: ); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); - void scanAvailableChannels(); - void notifyUpdateChannels(); + //void scanAvailableChannels(); + void notifyUpdateChannels(const QStringList& renameFrom, const QStringList& renameTo); void startScan(); void stopScan(); void initScan(); @@ -416,9 +424,7 @@ private: private slots: void networkManagerFinished(QNetworkReply *reply); void handleIndexInDeviceSetChanged(int index); - void handleChannelAdded(int deviceSetIndex, ChannelAPI* channel); - void handleChannelRemoved(int deviceSetIndex, ChannelAPI* channel); - void handleChannelStreamIndexChanged(int streamIndex, ChannelAPI* channel); + void channelsChanged(const QStringList& renameFrom, const QStringList& renameTo); void timeout(); }; diff --git a/plugins/channelrx/freqscanner/freqscannergui.cpp b/plugins/channelrx/freqscanner/freqscannergui.cpp index 71030f12b..68c92577a 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.cpp +++ b/plugins/channelrx/freqscanner/freqscannergui.cpp @@ -118,8 +118,7 @@ bool FreqScannerGUI::handleMessage(const Message& message) else if (FreqScanner::MsgReportChannels::match(message)) { FreqScanner::MsgReportChannels& report = (FreqScanner::MsgReportChannels&)message; - m_availableChannels = report.getChannels(); - updateChannelsList(m_availableChannels); + updateChannelsList(report.getChannels(), report.getRenameFrom(), report.getRenameTo()); return true; } else if (FreqScanner::MsgStatus::match(message)) @@ -212,7 +211,7 @@ bool FreqScannerGUI::handleMessage(const Message& message) return false; } -void FreqScannerGUI::updateChannelsCombo(QComboBox *combo, const QList& channels, const QString& channel, bool empty) +void FreqScannerGUI::updateChannelsCombo(QComboBox *combo, const AvailableChannelOrFeatureList& channels, const QString& channel, bool empty) { combo->blockSignals(true); combo->clear(); @@ -223,17 +222,8 @@ void FreqScannerGUI::updateChannelsCombo(QComboBox *combo, const QListgetDeviceSetIndex()) && (channel.m_channelIndex != m_freqScanner->getIndexInDeviceSet())) - { - QString name; - - if (channel.m_streamIndex < 0) { // Rx - name = QString("R%1:%2").arg(channel.m_deviceSetIndex).arg(channel.m_channelIndex); - } else { // MIMO - name = QString("M%1:%2.%3").arg(channel.m_deviceSetIndex).arg(channel.m_channelIndex).arg(channel.m_streamIndex); - } - - combo->addItem(name); + if ((channel.m_superIndex == m_freqScanner->getDeviceSetIndex()) && (channel.m_index != m_freqScanner->getIndexInDeviceSet())) { + combo->addItem(channel.getId()); } } @@ -250,8 +240,29 @@ void FreqScannerGUI::updateChannelsCombo(QComboBox *combo, const QListblockSignals(false); } -void FreqScannerGUI::updateChannelsList(const QList& channels) +void FreqScannerGUI::updateChannelsList(const AvailableChannelOrFeatureList& channels, const QStringList& renameFrom, const QStringList& renameTo) { + m_availableChannels = channels; + + // Update channel setting if it has been renamed + if (renameFrom.contains(m_settings.m_channel)) + { + m_settings.m_channel = renameTo[renameFrom.indexOf(m_settings.m_channel)]; + applySetting("channel"); + } + bool rename = false; + for (auto& setting : m_settings.m_frequencySettings) + { + if (renameFrom.contains(setting.m_channel)) + { + setting.m_channel = renameTo[renameFrom.indexOf(setting.m_channel)]; + rename = true; + } + } + if (rename) { + applySetting("frequencySettings"); + } + updateChannelsCombo(ui->channels, channels, m_settings.m_channel, false); for (int row = 0; row < ui->table->rowCount(); row++) @@ -515,10 +526,12 @@ void FreqScannerGUI::applySetting(const QString& settingsKey) void FreqScannerGUI::applySettings(const QStringList& settingsKeys, bool force) { + m_settingsKeys.append(settingsKeys); if (m_doApplySettings) { - FreqScanner::MsgConfigureFreqScanner* message = FreqScanner::MsgConfigureFreqScanner::create(m_settings, settingsKeys, force); + FreqScanner::MsgConfigureFreqScanner* message = FreqScanner::MsgConfigureFreqScanner::create(m_settings, m_settingsKeys, force); m_freqScanner->getInputMessageQueue()->push(message); + m_settingsKeys.clear(); } } diff --git a/plugins/channelrx/freqscanner/freqscannergui.h b/plugins/channelrx/freqscanner/freqscannergui.h index edc598950..4dc9dd484 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.h +++ b/plugins/channelrx/freqscanner/freqscannergui.h @@ -73,6 +73,7 @@ private: ChannelMarker m_channelMarker; RollupState m_rollupState; FreqScannerSettings m_settings; + QList m_settingsKeys; qint64 m_deviceCenterFrequency; bool m_doApplySettings; @@ -82,7 +83,7 @@ private: QMenu *m_menu; - QList m_availableChannels; + AvailableChannelOrFeatureList m_availableChannels; explicit FreqScannerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); virtual ~FreqScannerGUI(); @@ -98,8 +99,8 @@ private: void addRow(const FreqScannerSettings::FrequencySettings& frequencySettings); void updateAnnotation(int row); void updateAnnotations(); - void updateChannelsCombo(QComboBox *combo, const QList& channels, const QString& channel, bool empty); - void updateChannelsList(const QList& channels); + void updateChannelsCombo(QComboBox *combo, const AvailableChannelOrFeatureList& channels, const QString& channel, bool empty); + void updateChannelsList(const AvailableChannelOrFeatureList& channels, const QStringList& renameFrom, const QStringList& renameTo); void setAllEnabled(bool enable); void leaveEvent(QEvent*); diff --git a/plugins/channelrx/freqscanner/freqscannersettings.h b/plugins/channelrx/freqscanner/freqscannersettings.h index 439f06419..a1ec26b0b 100644 --- a/plugins/channelrx/freqscanner/freqscannersettings.h +++ b/plugins/channelrx/freqscanner/freqscannersettings.h @@ -31,17 +31,6 @@ class ChannelAPI; struct FreqScannerSettings { - struct AvailableChannel - { - int m_deviceSetIndex; - int m_channelIndex; - int m_streamIndex; - - AvailableChannel() = default; - AvailableChannel(const AvailableChannel&) = default; - AvailableChannel& operator=(const AvailableChannel&) = default; - }; - struct FrequencySettings { qint64 m_frequency; bool m_enabled; diff --git a/plugins/channelrx/radioastronomy/radioastronomy.cpp b/plugins/channelrx/radioastronomy/radioastronomy.cpp index baa76f478..7254a49f8 100644 --- a/plugins/channelrx/radioastronomy/radioastronomy.cpp +++ b/plugins/channelrx/radioastronomy/radioastronomy.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // -// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -67,10 +67,12 @@ const char * const RadioAstronomy::m_channelIdURI = "sdrangel.channel.radioastro const char * const RadioAstronomy::m_channelId = "RadioAstronomy"; RadioAstronomy::RadioAstronomy(DeviceAPI *deviceAPI) : - ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), - m_deviceAPI(deviceAPI), - m_basebandSampleRate(0), - m_sweeping(false) + ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), + m_deviceAPI(deviceAPI), + m_basebandSampleRate(0), + m_availableFeatureHandler({"sdrangel.feature.startracker"}, QStringList{"startracker.target"}), + m_availableRotatorHandler({"sdrangel.feature.gs232controller"}), + m_sweeping(false) { qDebug("RadioAstronomy::RadioAstronomy"); setObjectName(m_channelId); @@ -105,17 +107,26 @@ RadioAstronomy::RadioAstronomy(DeviceAPI *deviceAPI) : &RadioAstronomy::handleIndexInDeviceSetChanged ); QObject::connect( - MainCore::instance(), - &MainCore::featureAdded, + &m_availableFeatureHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &RadioAstronomy::handleFeatureAdded + &RadioAstronomy::handleFeatureMessageQueue ); QObject::connect( - MainCore::instance(), - &MainCore::featureRemoved, + &m_availableFeatureHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, - &RadioAstronomy::handleFeatureRemoved + &RadioAstronomy::featuresChanged ); + m_availableFeatureHandler.scanAvailableChannelsAndFeatures(); + + QObject::connect( + &m_availableRotatorHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, + this, + &RadioAstronomy::rotatorsChanged + ); + m_availableRotatorHandler.scanAvailableChannelsAndFeatures(); m_sweepTimer.setSingleShot(true); } @@ -123,17 +134,20 @@ RadioAstronomy::RadioAstronomy(DeviceAPI *deviceAPI) : RadioAstronomy::~RadioAstronomy() { qDebug("RadioAstronomy::~RadioAstronomy"); - QObject::disconnect( - MainCore::instance(), - &MainCore::featureRemoved, + QObject::disconnect(&m_availableFeatureHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &RadioAstronomy::handleFeatureRemoved + &RadioAstronomy::handleFeatureMessageQueue ); - QObject::disconnect( - MainCore::instance(), - &MainCore::featureAdded, + QObject::disconnect(&m_availableFeatureHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, - &RadioAstronomy::handleFeatureAdded + &RadioAstronomy::featuresChanged + ); + QObject::disconnect(&m_availableRotatorHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, + this, + &RadioAstronomy::rotatorsChanged ); QObject::disconnect( m_networkManager, @@ -194,8 +208,6 @@ void RadioAstronomy::start() m_basebandSink->getInputMessageQueue()->push(new DSPSignalNotification(m_basebandSampleRate, m_centerFrequency)); m_basebandSink->getInputMessageQueue()->push(RadioAstronomyBaseband::MsgConfigureRadioAstronomyBaseband::create(m_settings, true)); m_worker->getInputMessageQueue()->push(RadioAstronomyWorker::MsgConfigureRadioAstronomyWorker::create(m_settings, true)); - - scanAvailableFeatures(); } void RadioAstronomy::stop() @@ -330,7 +342,8 @@ bool RadioAstronomy::handleMessage(const Message& cmd) } else if (MsgScanAvailableFeatures::match(cmd)) { - scanAvailableFeatures(); + notifyUpdateFeatures({}, {}); + notifyUpdateRotators({}, {}); return true; } else @@ -753,22 +766,14 @@ void RadioAstronomy::applySettings(const RadioAstronomySettings& settings, bool { if (!settings.m_starTracker.isEmpty()) { - Feature *feature = nullptr; - - for (const auto& fval : m_availableFeatures) + int index = m_availableFeatures.indexOfLongId(settings.m_starTracker); + if (index >= 0) { - QString starTrackerText = tr("F%1:%2 %3").arg(fval.m_featureSetIndex).arg(fval.m_featureIndex).arg(fval.m_type); - - if (settings.m_starTracker == starTrackerText) - { - feature = m_availableFeatures.key(fval); - break; - } + m_selectedPipe = m_availableFeatures[index].m_object; } - - if (feature) { - m_selectedPipe = feature; - } else { + else + { + m_selectedPipe = nullptr; qDebug() << "RadioAstronomy::applySettings: No plugin corresponding to target " << settings.m_starTracker; } } @@ -1246,145 +1251,39 @@ void RadioAstronomy::handleIndexInDeviceSetChanged(int index) m_basebandSink->setFifoLabel(fifoLabel); } -void RadioAstronomy::scanAvailableFeatures() +void RadioAstronomy::featuresChanged(const QStringList& renameFrom, const QStringList& renameTo) { - qDebug("RadioAstronomy::scanAvailableFeatures"); - MainCore *mainCore = MainCore::instance(); - MessagePipes& messagePipes = mainCore->getMessagePipes(); - std::vector& featureSets = mainCore->getFeatureeSets(); - m_availableFeatures.clear(); - m_rotators.clear(); - - for (const auto& featureSet : featureSets) - { - for (int fei = 0; fei < featureSet->getNumberOfFeatures(); fei++) - { - Feature *feature = featureSet->getFeatureAt(fei); - - if (RadioAstronomySettings::m_pipeURIs.contains(feature->getURI())) - { - if (!m_availableFeatures.contains(feature)) - { - qDebug("RadioAstronomy::scanAvailableFeatures: register %d:%d %s (%p)", - featureSet->getIndex(), fei, qPrintable(feature->getURI()), feature); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(feature, this, "startracker.target"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleFeatureMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); - RadioAstronomySettings::AvailableFeature availableFeature = - RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; - m_availableFeatures[feature] = availableFeature; - } - } - else if (feature->getURI() == "sdrangel.feature.gs232controller") - { - RadioAstronomySettings::AvailableFeature rotator = - RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; - m_rotators[feature] = rotator; - } - } - } - - notifyUpdateFeatures(); - notifyUpdateRotators(); + m_availableFeatures = m_availableFeatureHandler.getAvailableChannelOrFeatureList(); + notifyUpdateFeatures(renameFrom, renameTo); } -void RadioAstronomy::notifyUpdateFeatures() + +void RadioAstronomy::notifyUpdateFeatures(const QStringList& renameFrom, const QStringList& renameTo) { if (getMessageQueueToGUI()) { - MsgReportAvailableFeatures *msg = MsgReportAvailableFeatures::create(); - msg->getFeatures() = m_availableFeatures.values(); + MsgReportAvailableFeatures *msg = MsgReportAvailableFeatures::create(renameFrom, renameTo); + msg->getFeatures() = m_availableFeatures; getMessageQueueToGUI()->push(msg); } } -void RadioAstronomy::notifyUpdateRotators() +void RadioAstronomy::rotatorsChanged(const QStringList& renameFrom, const QStringList& renameTo) +{ + m_rotators = m_availableRotatorHandler.getAvailableChannelOrFeatureList(); + notifyUpdateRotators(renameFrom, renameTo); +} + +void RadioAstronomy::notifyUpdateRotators(const QStringList& renameFrom, const QStringList& renameTo) { if (getMessageQueueToGUI()) { - MsgReportAvailableRotators *msg = MsgReportAvailableRotators::create(); - msg->getFeatures() = m_rotators.values(); + MsgReportAvailableRotators *msg = MsgReportAvailableRotators::create(renameFrom, renameTo); + msg->getFeatures() = m_rotators; getMessageQueueToGUI()->push(msg); } } -void RadioAstronomy::handleFeatureAdded(int featureSetIndex, Feature *feature) -{ - qDebug("RadioAstronomy::handleFeatureAdded: featureSetIndex: %d:%d feature: %s (%p)", - featureSetIndex, feature->getIndexInFeatureSet(), qPrintable(feature->getURI()), feature); - FeatureSet *featureSet = MainCore::instance()->getFeatureeSets()[featureSetIndex]; - - if (RadioAstronomySettings::m_pipeURIs.contains(feature->getURI())) - { - int fei = feature->getIndexInFeatureSet(); - - if (!m_availableFeatures.contains(feature)) - { - MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(feature, this, "startracker.target"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleFeatureMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &RadioAstronomy::handleMessagePipeToBeDeleted - ); - } - - RadioAstronomySettings::AvailableFeature availableFeature = - RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; - m_availableFeatures[feature] = availableFeature; - - notifyUpdateFeatures(); - } - else if (feature->getURI() == "sdrangel.feature.gs232controller") - { - if (!m_rotators.contains(feature)) - { - RadioAstronomySettings::AvailableFeature rotator = - RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), feature->getIndexInFeatureSet(), feature->getIdentifier()}; - m_rotators[feature] = rotator; - } - - notifyUpdateRotators(); - } -} - -void RadioAstronomy::handleFeatureRemoved(int featureSetIndex, Feature *feature) -{ - qDebug("RadioAstronomy::handleFeatureRemoved: featureSetIndex: %d (%p)", featureSetIndex, feature); - - if (m_rotators.contains(feature)) - { - m_rotators.remove(feature); - notifyUpdateRotators(); - } -} - -void RadioAstronomy::handleMessagePipeToBeDeleted(int reason, QObject* object) -{ - if ((reason == 0) && m_availableFeatures.contains((Feature*) object)) // producer (feature) - { - qDebug("RadioAstronomy::handleMessagePipeToBeDeleted: removing feature at (%p)", object); - m_availableFeatures.remove((Feature*) object); - notifyUpdateFeatures(); - } -} - void RadioAstronomy::handleFeatureMessageQueue(MessageQueue* messageQueue) { Message* message; diff --git a/plugins/channelrx/radioastronomy/radioastronomy.h b/plugins/channelrx/radioastronomy/radioastronomy.h index 1021f8590..bc1679bac 100644 --- a/plugins/channelrx/radioastronomy/radioastronomy.h +++ b/plugins/channelrx/radioastronomy/radioastronomy.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // -// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -31,6 +31,7 @@ #include "dsp/basebandsamplesink.h" #include "channel/channelapi.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" #include "radioastronomybaseband.h" #include "radioastronomysettings.h" @@ -329,17 +330,23 @@ public: MESSAGE_CLASS_DECLARATION public: - QList& getFeatures() { return m_availableFeatures; } + AvailableChannelOrFeatureList& getFeatures() { return m_availableFeatures; } + const QStringList& getRenameFrom() const { return m_renameFrom; } + const QStringList& getRenameTo() const { return m_renameTo; } - static MsgReportAvailableFeatures* create() { - return new MsgReportAvailableFeatures(); + static MsgReportAvailableFeatures* create(const QStringList& renameFrom, const QStringList& renameTo) { + return new MsgReportAvailableFeatures(renameFrom, renameTo); } private: - QList m_availableFeatures; + AvailableChannelOrFeatureList m_availableFeatures; + QStringList m_renameFrom; + QStringList m_renameTo; - MsgReportAvailableFeatures() : - Message() + MsgReportAvailableFeatures(const QStringList& renameFrom, const QStringList& renameTo) : + Message(), + m_renameFrom(renameFrom), + m_renameTo(renameTo) {} }; @@ -347,17 +354,24 @@ public: MESSAGE_CLASS_DECLARATION public: - QList& getFeatures() { return m_availableFeatures; } + AvailableChannelOrFeatureList& getFeatures() { return m_availableFeatures; } + const QStringList& getRenameFrom() const { return m_renameFrom; } + const QStringList& getRenameTo() const { return m_renameTo; } - static MsgReportAvailableRotators* create() { - return new MsgReportAvailableRotators(); + + static MsgReportAvailableRotators* create(const QStringList& renameFrom, const QStringList& renameTo) { + return new MsgReportAvailableRotators(renameFrom, renameTo); } private: - QList m_availableFeatures; + AvailableChannelOrFeatureList m_availableFeatures; + QStringList m_renameFrom; + QStringList m_renameTo; - MsgReportAvailableRotators() : - Message() + MsgReportAvailableRotators(const QStringList& renameFrom, const QStringList& renameTo) : + Message(), + m_renameFrom(renameFrom), + m_renameTo(renameTo) {} }; @@ -448,8 +462,10 @@ private: int m_basebandSampleRate; //!< stored from device message used when starting baseband sink qint64 m_centerFrequency; - QHash m_availableFeatures; - QHash m_rotators; + AvailableChannelOrFeatureHandler m_availableFeatureHandler; + AvailableChannelOrFeatureList m_availableFeatures; + AvailableChannelOrFeatureHandler m_availableRotatorHandler; + AvailableChannelOrFeatureList m_rotators; QObject *m_selectedPipe; QNetworkAccessManager *m_networkManager; @@ -482,9 +498,8 @@ private: void sweepStart(); void startCal(bool hot); void calComplete(MsgCalComplete* report); - void scanAvailableFeatures(); - void notifyUpdateFeatures(); - void notifyUpdateRotators(); + void notifyUpdateFeatures(const QStringList& renameFrom, const QStringList& renameTo); + void notifyUpdateRotators(const QStringList& renameFrom, const QStringList& renameTo); private slots: void networkManagerFinished(QNetworkReply *reply); @@ -496,9 +511,8 @@ private slots: void sweepNext(); void sweepComplete(); void handleIndexInDeviceSetChanged(int index); - void handleFeatureAdded(int featureSetIndex, Feature *feature); - void handleFeatureRemoved(int featureSetIndex, Feature *feature); - void handleMessagePipeToBeDeleted(int reason, QObject* object); + void featuresChanged(const QStringList& renameFrom, const QStringList& renameTo); + void rotatorsChanged(const QStringList& renameFrom, const QStringList& renameTo); void handleFeatureMessageQueue(MessageQueue* messageQueue); }; diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.cpp b/plugins/channelrx/radioastronomy/radioastronomygui.cpp index af8304c6b..1ccc60fb9 100644 --- a/plugins/channelrx/radioastronomy/radioastronomygui.cpp +++ b/plugins/channelrx/radioastronomy/radioastronomygui.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Edouard Griffiths, F4EXB // -// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -916,31 +916,33 @@ bool RadioAstronomyGUI::deserialize(const QByteArray& data) } } -void RadioAstronomyGUI::updateAvailableFeatures() +void RadioAstronomyGUI::updateAvailableFeatures(const AvailableChannelOrFeatureList& availableFeatures, const QStringList& renameFrom, const QStringList& renameTo) { - QString currentText = ui->starTracker->currentText(); + // Update starTracker settting if it has been renamed + if (renameFrom.contains(m_settings.m_starTracker)) + { + m_settings.m_starTracker = renameTo[renameFrom.indexOf(m_settings.m_starTracker)]; + applySettings(); + } + ui->starTracker->blockSignals(true); ui->starTracker->clear(); - for (const auto& feature : m_availableFeatures) { - ui->starTracker->addItem(tr("F%1:%2 %3").arg(feature.m_featureSetIndex).arg(feature.m_featureIndex).arg(feature.m_type)); + for (const auto& feature : availableFeatures) { + ui->starTracker->addItem(feature.getLongId()); } - if (currentText.isEmpty()) - { - if (m_availableFeatures.size() > 0) { - ui->starTracker->setCurrentIndex(0); - } - } - else - { - ui->starTracker->setCurrentIndex(ui->starTracker->findText(currentText)); + int idx = ui->starTracker->findText(m_settings.m_starTracker); + if (idx >= 0) { + ui->starTracker->setCurrentIndex(idx); + } else { + ui->starTracker->setCurrentIndex(0); } ui->starTracker->blockSignals(false); - QString newText = ui->starTracker->currentText(); - if (currentText != newText) + QString newText = ui->starTracker->currentText(); + if (m_settings.m_starTracker != newText) { m_settings.m_starTracker = newText; applySettings(); @@ -970,8 +972,7 @@ bool RadioAstronomyGUI::handleMessage(const Message& message) { qDebug("RadioAstronomyGUI::handleMessage: MsgReportAvailableFeatures"); RadioAstronomy::MsgReportAvailableFeatures& report = (RadioAstronomy::MsgReportAvailableFeatures&) message; - m_availableFeatures = report.getFeatures(); - updateAvailableFeatures(); + updateAvailableFeatures(report.getFeatures(), report.getRenameFrom(), report.getRenameTo()); return true; } else if (MainCore::MsgStarTrackerTarget::match(message)) @@ -1063,7 +1064,7 @@ bool RadioAstronomyGUI::handleMessage(const Message& message) else if (RadioAstronomy::MsgReportAvailableRotators::match(message)) { RadioAstronomy::MsgReportAvailableRotators& report = (RadioAstronomy::MsgReportAvailableRotators&) message; - updateRotatorList(report.getFeatures()); + updateRotatorList(report.getFeatures(), report.getRenameFrom(), report.getRenameTo()); return true; } @@ -1901,11 +1902,11 @@ void RadioAstronomyGUI::on_loadSpectrumData_clicked() void RadioAstronomyGUI::on_powerTable_cellDoubleClicked(int row, int column) { - if ((column >= POWER_COL_RA) && (column >= POWER_COL_EL)) + if ((column >= POWER_COL_RA) && (column <= POWER_COL_EL)) { // Display target in Star Tracker QList starTrackerPipes; - MainCore::instance()->getMessagePipes().getMessagePipes(this, "startracker.display", starTrackerPipes); + MainCore::instance()->getMessagePipes().getMessagePipes(m_radioAstronomy, "startracker.display", starTrackerPipes); for (const auto& pipe : starTrackerPipes) { @@ -2604,17 +2605,22 @@ void RadioAstronomyGUI::tick() m_tickCount++; } -void RadioAstronomyGUI::updateRotatorList(const QList& rotators) +void RadioAstronomyGUI::updateRotatorList(const AvailableChannelOrFeatureList& rotators, const QStringList& renameFrom, const QStringList& renameTo) { + // Update rotator settting if it has been renamed + if (renameFrom.contains(m_settings.m_rotator)) + { + m_settings.m_rotator = renameTo[renameFrom.indexOf(m_settings.m_rotator)]; + applySettings(); + } + // Update list of rotators ui->rotator->blockSignals(true); ui->rotator->clear(); ui->rotator->addItem("None"); - for (const auto& rotator : rotators) - { - QString name = QString("F%1:%2 %3").arg(rotator.m_featureSetIndex).arg(rotator.m_featureIndex).arg(rotator.m_type); - ui->rotator->addItem(name); + for (const auto& rotator : rotators) { + ui->rotator->addItem(rotator.getLongId()); } // Rotator feature can be created after this plugin, so select it @@ -4335,7 +4341,7 @@ void RadioAstronomyGUI::updateLoSMarker(const QString& name, float l, float b, f { // Send to Star Tracker QList starTrackerPipes; - MainCore::instance()->getMessagePipes().getMessagePipes(this, "startracker.display", starTrackerPipes); + MainCore::instance()->getMessagePipes().getMessagePipes(m_radioAstronomy, "startracker.display", starTrackerPipes); for (const auto& pipe : starTrackerPipes) { @@ -4794,7 +4800,7 @@ void RadioAstronomyGUI::on_spectrumIndex_valueChanged(int value) // Display target in Star Tracker QList starTrackerPipes; - MainCore::instance()->getMessagePipes().getMessagePipes(this, "startracker.display", starTrackerPipes); + MainCore::instance()->getMessagePipes().getMessagePipes(m_radioAstronomy, "startracker.display", starTrackerPipes); for (const auto& pipe : starTrackerPipes) { diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.h b/plugins/channelrx/radioastronomy/radioastronomygui.h index 9c59404a8..a391a9eb1 100644 --- a/plugins/channelrx/radioastronomy/radioastronomygui.h +++ b/plugins/channelrx/radioastronomy/radioastronomygui.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Edouard Griffiths, F4EXB // -// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -235,7 +235,6 @@ private: RollupState m_rollupState; RadioAstronomySettings m_settings; bool m_doApplySettings; - QList m_availableFeatures; int m_basebandSampleRate; quint64 m_centerFrequency; @@ -351,8 +350,8 @@ private: void displaySettings(); void displaySpectrumLineFrequency(); void displayRunModeSettings(); - void updateAvailableFeatures(); - void updateRotatorList(const QList& rotators); + void updateAvailableFeatures(const AvailableChannelOrFeatureList& availableFeatures, const QStringList& renameFrom, const QStringList& renameTo); + void updateRotatorList(const AvailableChannelOrFeatureList& rotators, const QStringList& renameFrom, const QStringList& renameTo); bool handleMessage(const Message& message); void makeUIConnections(); void updateAbsoluteCenterFrequency(); diff --git a/plugins/channelrx/radioastronomy/radioastronomysettings.cpp b/plugins/channelrx/radioastronomy/radioastronomysettings.cpp index dfb924fd1..953aec450 100644 --- a/plugins/channelrx/radioastronomy/radioastronomysettings.cpp +++ b/plugins/channelrx/radioastronomy/radioastronomysettings.cpp @@ -23,14 +23,6 @@ #include "settings/serializable.h" #include "radioastronomysettings.h" -const QStringList RadioAstronomySettings::m_pipeTypes = { - QStringLiteral("StarTracker") -}; - -const QStringList RadioAstronomySettings::m_pipeURIs = { - QStringLiteral("sdrangel.feature.startracker") -}; - RadioAstronomySettings::RadioAstronomySettings() : m_channelMarker(nullptr), m_rollupState(nullptr) diff --git a/plugins/channelrx/radioastronomy/radioastronomysettings.h b/plugins/channelrx/radioastronomy/radioastronomysettings.h index 02f8e447a..509bb9048 100644 --- a/plugins/channelrx/radioastronomy/radioastronomysettings.h +++ b/plugins/channelrx/radioastronomy/radioastronomysettings.h @@ -35,20 +35,6 @@ class Serializable; struct RadioAstronomySettings { - struct AvailableFeature - { - int m_featureSetIndex; - int m_featureIndex; - QString m_type; - - AvailableFeature() = default; - AvailableFeature(const AvailableFeature&) = default; - AvailableFeature& operator=(const AvailableFeature&) = default; - bool operator==(const AvailableFeature& a) const { - return (m_featureSetIndex == a.m_featureSetIndex) && (m_featureIndex == a.m_featureIndex) && (m_type == a.m_type); - } - }; - int m_inputFrequencyOffset; int m_sampleRate; int m_rfBandwidth; @@ -244,9 +230,6 @@ struct RadioAstronomySettings void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } QByteArray serialize() const; bool deserialize(const QByteArray& data); - - static const QStringList m_pipeTypes; - static const QStringList m_pipeURIs; }; #endif /* INCLUDE_RADIOASTRONOMYSETTINGS_H */ diff --git a/plugins/feature/CMakeLists.txt b/plugins/feature/CMakeLists.txt index 8c1f12ccb..1be829154 100644 --- a/plugins/feature/CMakeLists.txt +++ b/plugins/feature/CMakeLists.txt @@ -12,6 +12,11 @@ else() message(STATUS "Not building map (ENABLE_FEATURE_MAP=${ENABLE_FEATURE_MAP} Qt${QT_DEFAULT_MAJOR_VERSION}Quick_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}Quick_FOUND} Qt${QT_DEFAULT_MAJOR_VERSION}QuickWidgets_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}QuickWidgets_FOUND} Qt${QT_DEFAULT_MAJOR_VERSION}Positioning_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}Positioning_FOUND} Qt${QT_DEFAULT_MAJOR_VERSION}Location_FOUND=${Qt${QT_DEFAULT_MAJOR_VERSION}Location_FOUND})") endif() +# WebEngine on Qt5, WebEngineCore on Qt6 +if(ENABLE_FEATURE_SKYMAP AND Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND OR Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND) + add_subdirectory(skymap) +endif() + if (ENABLE_FEATURE_VORLOCALIZER AND Qt${QT_DEFAULT_MAJOR_VERSION}Quick_FOUND AND Qt${QT_DEFAULT_MAJOR_VERSION}QuickWidgets_FOUND AND Qt${QT_DEFAULT_MAJOR_VERSION}Positioning_FOUND) add_subdirectory(vorlocalizer) else() diff --git a/plugins/feature/ais/ais.cpp b/plugins/feature/ais/ais.cpp index aca0bf9e0..484b9a32a 100644 --- a/plugins/feature/ais/ais.cpp +++ b/plugins/feature/ais/ais.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2021 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -41,7 +41,8 @@ const char* const AIS::m_featureIdURI = "sdrangel.feature.ais"; const char* const AIS::m_featureId = "AIS"; AIS::AIS(WebAPIAdapterInterface *webAPIAdapterInterface) : - Feature(m_featureIdURI, webAPIAdapterInterface) + Feature(m_featureIdURI, webAPIAdapterInterface), + m_availableChannelHandler({"sdrangel.channel.aisdemod"}, QStringList{"ais"}) { qDebug("AIS::AIS: webAPIAdapterInterface: %p", webAPIAdapterInterface); setObjectName(m_featureId); @@ -54,23 +55,20 @@ AIS::AIS(WebAPIAdapterInterface *webAPIAdapterInterface) : this, &AIS::networkManagerFinished ); - scanAvailableChannels(); QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &AIS::handleChannelAdded - ); + &AIS::handleChannelMessageQueue); } AIS::~AIS() { QObject::disconnect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &AIS::handleChannelAdded - ); + &AIS::handleChannelMessageQueue); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -362,90 +360,6 @@ void AIS::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } -void AIS::scanAvailableChannels() -{ - MainCore *mainCore = MainCore::instance(); - MessagePipes& messagePipes = mainCore->getMessagePipes(); - std::vector& deviceSets = mainCore->getDeviceSets(); - m_availableChannels.clear(); - - for (const auto& deviceSet : deviceSets) - { - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine) - { - for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) - { - ChannelAPI *channel = deviceSet->getChannelAt(chi); - - if ((channel->getURI() == "sdrangel.channel.aisdemod") && !m_availableChannels.contains(channel)) - { - qDebug("AIS::scanAvailableChannels: register %d:%d (%p)", deviceSet->getIndex(), chi, channel); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "ais"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &AIS::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } - } - } -} - -void AIS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) -{ - qDebug("AIS::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - std::vector& deviceSets = MainCore::instance()->getDeviceSets(); - DeviceSet *deviceSet = deviceSets[deviceSetIndex]; - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine && (channel->getURI() == "sdrangel.channel.aisdemod")) - { - if (!m_availableChannels.contains(channel)) - { - MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "ais"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &AIS::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } -} - -void AIS::handleMessagePipeToBeDeleted(int reason, QObject* object) -{ - if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) - { - qDebug("AIS::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } -} - void AIS::handleChannelMessageQueue(MessageQueue* messageQueue) { Message* message; diff --git a/plugins/feature/ais/ais.h b/plugins/feature/ais/ais.h index 937ab54a4..ae089d074 100644 --- a/plugins/feature/ais/ais.h +++ b/plugins/feature/ais/ais.h @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // -// Copyright (C) 2021-2022 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -25,6 +25,7 @@ #include "feature/feature.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" #include "aissettings.h" @@ -101,7 +102,8 @@ public: private: AISSettings m_settings; - QSet m_availableChannels; + AvailableChannelOrFeatureHandler m_availableChannelHandler; + AvailableChannelOrFeatureList m_availableChannels; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -110,12 +112,9 @@ private: void stop(); void applySettings(const AISSettings& settings, const QList& settingsKeys, bool force = false); void webapiReverseSendSettings(const QList& featureSettingsKeys, const AISSettings& settings, bool force); - void scanAvailableChannels(); private slots: void networkManagerFinished(QNetworkReply *reply); - void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); - void handleMessagePipeToBeDeleted(int reason, QObject* object); void handleChannelMessageQueue(MessageQueue* messageQueue); }; diff --git a/plugins/feature/ais/aisgui.cpp b/plugins/feature/ais/aisgui.cpp index 05945886d..9ce611f6a 100644 --- a/plugins/feature/ais/aisgui.cpp +++ b/plugins/feature/ais/aisgui.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -47,7 +47,7 @@ QStringList AISGUI::m_shipModels = { "tug_20m.glbe", "tug_30m_1.glbe", "tug_30m_2.glbe", "tug_30m_3.glbe", "cargo_75m.glbe", "tanker_50m.glbe", "dredger_53m.glbe", "trawler_22m.glbe", - "speedboat_8m.glbe", "yacht_10m.glbe", "yacht_20m.glbe", "yacht_42m.glbe" + "speedboat_8m.glbe", /*"yacht_10m.glbe",*/ "yacht_20m.glbe", "yacht_42m.glbe" }; QStringList AISGUI::m_sailboatModels = { @@ -236,6 +236,7 @@ AISGUI::AISGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur displaySettings(); applySettings(true); + m_resizer.enableChildMouseTracking(); } AISGUI::~AISGUI() @@ -845,14 +846,14 @@ void AISGUI::getImageAndModel(const QString &type, const QString &shipType, int { vessel->m_model = "cargo_75m.glbe"; } - else if (length < 200) + else /*if (length < 200)*/ { vessel->m_model = "cargo_190m.glbe"; } - else + /*else { vessel->m_model = "cargo_230m.glbe"; - } + }*/ } else if (shipType == "Tanker") { @@ -905,10 +906,10 @@ void AISGUI::getImageAndModel(const QString &type, const QString &shipType, int { vessel->m_model = "speedboat_8m.glbe"; } - else if (length < 18) + /*else if (length < 18) { vessel->m_model = "yacht_10m.glbe"; - } + }*/ else if (length < 32) { vessel->m_model = "yacht_20m.glbe"; diff --git a/plugins/feature/aprs/aprs.cpp b/plugins/feature/aprs/aprs.cpp index 4c6ed9583..8bd06c23a 100644 --- a/plugins/feature/aprs/aprs.cpp +++ b/plugins/feature/aprs/aprs.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -46,7 +46,8 @@ const char* const APRS::m_featureId = "APRS"; APRS::APRS(WebAPIAdapterInterface *webAPIAdapterInterface) : Feature(m_featureIdURI, webAPIAdapterInterface), m_thread(nullptr), - m_worker(nullptr) + m_worker(nullptr), + m_availableChannelHandler(APRSSettings::m_pipeURIs, QStringList{"packets"}) { qDebug("APRS::APRS: webAPIAdapterInterface: %p", webAPIAdapterInterface); setObjectName(m_featureId); @@ -59,23 +60,31 @@ APRS::APRS(WebAPIAdapterInterface *webAPIAdapterInterface) : this, &APRS::networkManagerFinished ); - scanAvailableChannels(); QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &APRS::handleChannelAdded - ); + &APRS::handleChannelMessageQueue); + QObject::connect( + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, + this, + &APRS::channelsChanged); + m_availableChannelHandler.scanAvailableChannelsAndFeatures(); } APRS::~APRS() { QObject::disconnect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &APRS::handleChannelAdded - ); + &APRS::handleChannelMessageQueue); + QObject::disconnect( + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, + this, + &APRS::channelsChanged); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -858,6 +867,7 @@ void APRS::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } +/* void APRS::scanAvailableChannels() { MainCore *mainCore = MainCore::instance(); @@ -905,18 +915,25 @@ void APRS::scanAvailableChannels() } } } +*/ + +void APRS::channelsChanged() +{ + m_availableChannels = m_availableChannelHandler.getAvailableChannelOrFeatureList(); + notifyUpdateChannels(); +} void APRS::notifyUpdateChannels() { if (getMessageQueueToGUI()) { MsgReportAvailableChannels *msg = MsgReportAvailableChannels::create(); - msg->getChannels() = m_availableChannels.values(); + msg->getChannels() = m_availableChannels; getMessageQueueToGUI()->push(msg); } } -void APRS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) +/*void APRS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) { qDebug("APRS::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); @@ -964,7 +981,7 @@ void APRS::handleMessagePipeToBeDeleted(int reason, QObject* object) m_availableChannels.remove((ChannelAPI*) object); notifyUpdateChannels(); } -} +}*/ void APRS::handleChannelMessageQueue(MessageQueue* messageQueue) { diff --git a/plugins/feature/aprs/aprs.h b/plugins/feature/aprs/aprs.h index 8db360d15..a5de2ac55 100644 --- a/plugins/feature/aprs/aprs.h +++ b/plugins/feature/aprs/aprs.h @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // -// Copyright (C) 2021-2022 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -26,6 +26,7 @@ #include "feature/feature.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" #include "aprssettings.h" @@ -104,14 +105,14 @@ public: MESSAGE_CLASS_DECLARATION public: - QList& getChannels() { return m_availableChannels; } + AvailableChannelOrFeatureList& getChannels() { return m_availableChannels; } static MsgReportAvailableChannels* create() { return new MsgReportAvailableChannels(); } private: - QList m_availableChannels; + AvailableChannelOrFeatureList m_availableChannels; MsgReportAvailableChannels() : Message() @@ -160,7 +161,8 @@ private: QThread *m_thread; APRSWorker *m_worker; APRSSettings m_settings; - QHash m_availableChannels; + AvailableChannelOrFeatureHandler m_availableChannelHandler; + AvailableChannelOrFeatureList m_availableChannels; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -169,14 +171,12 @@ private: void stop(); void applySettings(const APRSSettings& settings, const QList& settingsKeys, bool force = false); void webapiReverseSendSettings(const QList& featureSettingsKeys, const APRSSettings& settings, bool force); - void scanAvailableChannels(); void notifyUpdateChannels(); private slots: void networkManagerFinished(QNetworkReply *reply); - void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); - void handleMessagePipeToBeDeleted(int reason, QObject* object); void handleChannelMessageQueue(MessageQueue* messageQueue); + void channelsChanged(); }; #endif // INCLUDE_FEATURE_APRS_H_ diff --git a/plugins/feature/aprs/aprsgui.cpp b/plugins/feature/aprs/aprsgui.cpp index cc1ffa936..4abcdd5b2 100644 --- a/plugins/feature/aprs/aprsgui.cpp +++ b/plugins/feature/aprs/aprsgui.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -708,7 +708,7 @@ void APRSGUI::updateChannelList() ui->sourcePipes->clear(); for (const auto& channel : m_availableChannels) { - ui->sourcePipes->addItem(tr("R%1:%2 %3").arg(channel.m_deviceSetIndex).arg(channel.m_channelIndex).arg(channel.m_type)); + ui->sourcePipes->addItem(channel.getLongId()); } ui->sourcePipes->blockSignals(false); diff --git a/plugins/feature/aprs/aprsgui.h b/plugins/feature/aprs/aprsgui.h index 148fe0a86..abc301ac8 100644 --- a/plugins/feature/aprs/aprsgui.h +++ b/plugins/feature/aprs/aprsgui.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -30,6 +30,7 @@ #include "util/messagequeue.h" #include "util/aprs.h" #include "settings/rollupstate.h" +#include "availablechannelorfeature.h" #include "aprssettings.h" @@ -123,7 +124,7 @@ private: QList m_settingsKeys; RollupState m_rollupState; bool m_doApplySettings; - QList m_availableChannels; + AvailableChannelOrFeatureList m_availableChannels; APRS* m_aprs; MessageQueue m_inputMessageQueue; diff --git a/plugins/feature/aprs/aprssettings.h b/plugins/feature/aprs/aprssettings.h index 1afc1ada0..4117df599 100644 --- a/plugins/feature/aprs/aprssettings.h +++ b/plugins/feature/aprs/aprssettings.h @@ -2,7 +2,7 @@ // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // // written by Christian Daniel // // Copyright (C) 2015-2020, 2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2020-2021 Jon Beniston, M7RCE // +// Copyright (C) 2020-2024 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 // @@ -38,17 +38,6 @@ class Serializable; struct APRSSettings { - struct AvailableChannel - { - int m_deviceSetIndex; - int m_channelIndex; - QString m_type; - - AvailableChannel() = default; - AvailableChannel(const AvailableChannel&) = default; - AvailableChannel& operator=(const AvailableChannel&) = default; - }; - QString m_igateServer; int m_igatePort; QString m_igateCallsign; diff --git a/plugins/feature/aprs/readme.md b/plugins/feature/aprs/readme.md index f81f4b0bf..39125f2ff 100644 --- a/plugins/feature/aprs/readme.md +++ b/plugins/feature/aprs/readme.md @@ -48,4 +48,4 @@ APRS icons are from: https://github.com/hessu/aprs-symbols Full details of the API can be found in the Swagger documentation. Here is a quick example of how to enable the APRS-IS IGate: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "APRS", "APRSSettings": { "igateCallsign": "MYCALLSIGN", "igatePasscode": "12345", "igateFilter": "r/50.2/10.2/25", "igateEnabled": 1 }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "APRS", "APRSSettings": { "igateCallsign": "MYCALLSIGN", "igatePasscode": "12345", "igateFilter": "r/50.2/10.2/25", "igateEnabled": 1 }}' diff --git a/plugins/feature/gs232controller/gs232controller.cpp b/plugins/feature/gs232controller/gs232controller.cpp index b9e18fb94..dff0774c1 100644 --- a/plugins/feature/gs232controller/gs232controller.cpp +++ b/plugins/feature/gs232controller/gs232controller.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2020-2023 Jon Beniston, M7RCE // +// Copyright (C) 2020-2024 Jon Beniston, M7RCE // // Copyright (C) 2020-2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // // // @@ -56,6 +56,8 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) Feature(m_featureIdURI, webAPIAdapterInterface), m_thread(nullptr), m_worker(nullptr), + m_availableChannelOrFeatureHandler(GS232ControllerSettings::m_pipeURIs), + m_selectedPipe(nullptr), m_currentAzimuth(0.0f), m_currentElevation(0.0f) { @@ -63,7 +65,6 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) setObjectName(m_featureId); m_state = StIdle; m_errorMessage = "GS232Controller error"; - m_selectedPipe = nullptr; m_networkManager = new QNetworkAccessManager(); QObject::connect( m_networkManager, @@ -71,30 +72,21 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) this, &GS232Controller::networkManagerFinished ); + QObject::connect( - MainCore::instance(), - &MainCore::featureAdded, + &m_availableChannelOrFeatureHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, - &GS232Controller::handleFeatureAdded + &GS232Controller::channelsOrFeaturesChanged ); QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelOrFeatureHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &GS232Controller::handleChannelAdded - ); - QObject::connect( - MainCore::instance(), - &MainCore::featureRemoved, - this, - &GS232Controller::handleFeatureRemoved - ); - QObject::connect( - MainCore::instance(), - &MainCore::channelRemoved, - this, - &GS232Controller::handleChannelRemoved + &GS232Controller::handlePipeMessageQueue ); + m_availableChannelOrFeatureHandler.scanAvailableChannelsAndFeatures(); + connect(&m_timer, &QTimer::timeout, this, &GS232Controller::scanSerialPorts); m_timer.start(5000); } @@ -104,28 +96,16 @@ GS232Controller::~GS232Controller() m_timer.stop(); disconnect(&m_timer, &QTimer::timeout, this, &GS232Controller::scanSerialPorts); QObject::disconnect( - MainCore::instance(), - &MainCore::channelRemoved, + &m_availableChannelOrFeatureHandler, + &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, - &GS232Controller::handleChannelRemoved + &GS232Controller::channelsOrFeaturesChanged ); QObject::disconnect( - MainCore::instance(), - &MainCore::featureRemoved, + &m_availableChannelOrFeatureHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &GS232Controller::handleFeatureRemoved - ); - QObject::disconnect( - MainCore::instance(), - &MainCore::channelAdded, - this, - &GS232Controller::handleChannelAdded - ); - QObject::disconnect( - MainCore::instance(), - &MainCore::featureAdded, - this, - &GS232Controller::handleFeatureAdded + &GS232Controller::handlePipeMessageQueue ); QObject::disconnect( m_networkManager, @@ -142,7 +122,7 @@ void GS232Controller::start() qDebug("GS232Controller::start"); m_thread = new QThread(); - m_worker = new GS232ControllerWorker(); + m_worker = new GS232ControllerWorker(this); m_worker->moveToThread(m_thread); QObject::connect(m_thread, &QThread::started, m_worker, &GS232ControllerWorker::startWork); QObject::connect(m_thread, &QThread::finished, m_worker, &QObject::deleteLater); @@ -154,8 +134,6 @@ void GS232Controller::start() GS232ControllerWorker::MsgConfigureGS232ControllerWorker *msg = GS232ControllerWorker::MsgConfigureGS232ControllerWorker::create(m_settings, QList(), true); m_worker->getInputMessageQueue()->push(msg); - - scanAvailableChannelsAndFeatures(); } void GS232Controller::stop() @@ -210,7 +188,7 @@ bool GS232Controller::handleMessage(const Message& cmd) } else if (MsgScanAvailableChannelOrFeatures::match(cmd)) { - scanAvailableChannelsAndFeatures(); + notifyUpdate({}, {}); return true; } else if (GS232ControllerReport::MsgReportAzAl::match(cmd)) @@ -248,8 +226,6 @@ bool GS232Controller::handleMessage(const Message& cmd) applySettings(m_settings, QList{"azimuth", "elevation"}); } } - else - qDebug() << "GS232Controller::handleMessage: No match " << msg.getPipeSource() << " " << m_selectedPipe; } return true; } @@ -306,57 +282,12 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, con { qDebug() << "GS232Controller::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force; - // if ((m_settings.m_source != settings.m_source) - // || (!settings.m_source.isEmpty() && (m_selectedPipe == nullptr)) // Change in available pipes - // || force) - if (settingsKeys.contains("source") || (!settings.m_source.isEmpty() && (m_selectedPipe == nullptr)) // Change in available pipes || force) { - MainCore *mainCore = MainCore::instance(); - MessagePipes& messagePipes = mainCore->getMessagePipes(); - - if (m_selectedPipe) - { - qDebug("GS232Controller::applySettings: unregister %s (%p)", qPrintable(m_selectedPipe->objectName()), m_selectedPipe); - messagePipes.unregisterProducerToConsumer(m_selectedPipe, this, "target"); - } - - if (!settings.m_source.isEmpty()) - { - QObject *object = nullptr; - - for (const auto& oval : m_availableChannelOrFeatures) - { - QString itemText = tr("%1%2:%3 %4") - .arg(oval.m_kind) - .arg(oval.m_superIndex) - .arg(oval.m_index) - .arg(oval.m_type); - - if (settings.m_source == itemText) - { - object = m_availableChannelOrFeatures.key(oval); - break; - } - } - - if (object) - { - registerPipe(object); - m_selectedPipe = object; - } - else - { - m_selectedPipe = nullptr; - qDebug() << "GS232Controller::applySettings: No plugin corresponding to source " << settings.m_source; - } - } - else - { - m_selectedPipe = nullptr; - } + m_availableChannelOrFeatureHandler.deregisterPipes(m_selectedPipe, {"target"}); + m_selectedPipe = m_availableChannelOrFeatureHandler.registerPipes(settings.m_source, {"target"}); } GS232ControllerWorker::MsgConfigureGS232ControllerWorker *msg = GS232ControllerWorker::MsgConfigureGS232ControllerWorker::create( @@ -724,12 +655,7 @@ void GS232Controller::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& r for (const auto& item : m_availableChannelOrFeatures) { - QString itemText = tr("%1%2:%3 %4") - .arg(item.m_kind) - .arg(item.m_superIndex) - .arg(item.m_index) - .arg(item.m_type); - + QString itemText = item.getLongId(); response.getGs232ControllerReport()->getSources()->append(new QString(itemText)); } @@ -769,163 +695,22 @@ void GS232Controller::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } -void GS232Controller::scanAvailableChannelsAndFeatures() +void GS232Controller::channelsOrFeaturesChanged(const QStringList& renameFrom, const QStringList& renameTo) { - qDebug("GS232Controller::scanAvailableChannelsAndFeatures"); - MainCore *mainCore = MainCore::instance(); - std::vector& featureSets = mainCore->getFeatureeSets(); - m_availableChannelOrFeatures.clear(); - - for (const auto& featureSet : featureSets) - { - for (int fei = 0; fei < featureSet->getNumberOfFeatures(); fei++) - { - Feature *feature = featureSet->getFeatureAt(fei); - - if (GS232ControllerSettings::m_pipeURIs.contains(feature->getURI()) && !m_availableChannelOrFeatures.contains(feature)) - { - qDebug("GS232Controller::scanAvailableChannelsAndFeatures: store feature %d:%d %s (%p)", - featureSet->getIndex(), fei, qPrintable(feature->getURI()), feature); - GS232ControllerSettings::AvailableChannelOrFeature availableItem = - GS232ControllerSettings::AvailableChannelOrFeature{"F", featureSet->getIndex(), fei, feature->getIdentifier()}; - m_availableChannelOrFeatures[feature] = availableItem; - } - } - } - - std::vector& deviceSets = mainCore->getDeviceSets(); - - for (const auto& deviceSet : deviceSets) - { - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine) - { - for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) - { - ChannelAPI *channel = deviceSet->getChannelAt(chi); - - if (GS232ControllerSettings::m_pipeURIs.contains(channel->getURI()) && !m_availableChannelOrFeatures.contains(channel)) - { - qDebug("GS232Controller::scanAvailableChannelsAndFeatures: store channel %d:%d %s (%p)", - deviceSet->getIndex(), chi, qPrintable(channel->getURI()), channel); - GS232ControllerSettings::AvailableChannelOrFeature availableItem = - GS232ControllerSettings::AvailableChannelOrFeature{"R", deviceSet->getIndex(), chi, channel->getIdentifier()}; - m_availableChannelOrFeatures[channel] = availableItem; - } - } - } - } - - notifyUpdate(); + m_availableChannelOrFeatures = m_availableChannelOrFeatureHandler.getAvailableChannelOrFeatureList(); + notifyUpdate(renameFrom, renameTo); } -void GS232Controller::notifyUpdate() +void GS232Controller::notifyUpdate(const QStringList& renameFrom, const QStringList& renameTo) { if (getMessageQueueToGUI()) { - MsgReportAvailableChannelOrFeatures *msg = MsgReportAvailableChannelOrFeatures::create(); - msg->getItems() = m_availableChannelOrFeatures.values(); + MsgReportAvailableChannelOrFeatures *msg = MsgReportAvailableChannelOrFeatures::create(renameFrom, renameTo); + msg->getItems() = m_availableChannelOrFeatures; getMessageQueueToGUI()->push(msg); } } -void GS232Controller::handleFeatureAdded(int featureSetIndex, Feature *feature) -{ - qDebug("GS232Controller::handleFeatureAdded: featureSetIndex: %d:%d feature: %s (%p)", - featureSetIndex, feature->getIndexInFeatureSet(), qPrintable(feature->getURI()), feature); - FeatureSet *featureSet = MainCore::instance()->getFeatureeSets()[featureSetIndex]; - - if (GS232ControllerSettings::m_pipeURIs.contains(feature->getURI())) - { - GS232ControllerSettings::AvailableChannelOrFeature availableItem = - GS232ControllerSettings::AvailableChannelOrFeature{ - "F", - featureSet->getIndex(), - feature->getIndexInFeatureSet(), - feature->getIdentifier() - }; - m_availableChannelOrFeatures[feature] = availableItem; - - notifyUpdate(); - } -} - -void GS232Controller::handleFeatureRemoved(int featureSetIndex, Feature *feature) -{ - qDebug("GS232Controller::handleFeatureRemoved: featureSetIndex: %d (%p)", featureSetIndex, feature); - - if (m_availableChannelOrFeatures.contains(feature)) - { - m_availableChannelOrFeatures.remove(feature); - notifyUpdate(); - } -} - -void GS232Controller::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) -{ - qDebug("GS232Controller::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - DeviceSet *deviceSet = MainCore::instance()->getDeviceSets()[deviceSetIndex]; - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine && GS232ControllerSettings::m_pipeURIs.contains(channel->getURI())) - { - GS232ControllerSettings::AvailableChannelOrFeature availableItem = - GS232ControllerSettings::AvailableChannelOrFeature{ - "R", - deviceSet->getIndex(), - channel->getIndexInDeviceSet(), - channel->getIdentifier() - }; - m_availableChannelOrFeatures[channel] = availableItem; - - notifyUpdate(); - } -} - -void GS232Controller::handleChannelRemoved(int deviceSetIndex, ChannelAPI *channel) -{ - qDebug("GS232Controller::handleChannelRemoved: deviceSetIndex: %d (%p)", deviceSetIndex, channel); - - if (m_availableChannelOrFeatures.contains(channel)) - { - m_availableChannelOrFeatures.remove(channel); - notifyUpdate(); - } -} - -void GS232Controller::registerPipe(QObject *object) -{ - qDebug("GS232Controller::registerPipe: register %s (%p)", qPrintable(object->objectName()), object); - MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(object, this, "target"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handlePipeMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &GS232Controller::handleMessagePipeToBeDeleted - ); -} - -void GS232Controller::handleMessagePipeToBeDeleted(int reason, QObject* object) -{ - if ((reason == 0) && m_availableChannelOrFeatures.contains(object)) // producer - { - qDebug("GS232Controller::handleMessagePipeToBeDeleted: removing channel or feature at (%p)", object); - m_availableChannelOrFeatures.remove(object); - notifyUpdate(); - } -} - void GS232Controller::handlePipeMessageQueue(MessageQueue* messageQueue) { Message* message; diff --git a/plugins/feature/gs232controller/gs232controller.h b/plugins/feature/gs232controller/gs232controller.h index 79f2ac9db..83cd3272d 100644 --- a/plugins/feature/gs232controller/gs232controller.h +++ b/plugins/feature/gs232controller/gs232controller.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2020-2023 Jon Beniston, M7RCE // +// Copyright (C) 2020-2024 Jon Beniston, M7RCE // // Copyright (C) 2020-2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // // // @@ -27,6 +27,8 @@ #include "feature/feature.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" +#include "maincore.h" #include "gs232controllersettings.h" @@ -110,17 +112,23 @@ public: MESSAGE_CLASS_DECLARATION public: - QList& getItems() { return m_availableChannelOrFeatures; } + AvailableChannelOrFeatureList& getItems() { return m_availableChannelOrFeatures; } + const QStringList& getRenameFrom() const { return m_renameFrom; } + const QStringList& getRenameTo() const { return m_renameTo; } - static MsgReportAvailableChannelOrFeatures* create() { - return new MsgReportAvailableChannelOrFeatures(); + static MsgReportAvailableChannelOrFeatures* create(const QStringList& renameFrom, const QStringList& renameTo) { + return new MsgReportAvailableChannelOrFeatures(renameFrom, renameTo); } private: - QList m_availableChannelOrFeatures; + AvailableChannelOrFeatureList m_availableChannelOrFeatures; + QStringList m_renameFrom; + QStringList m_renameTo; - MsgReportAvailableChannelOrFeatures() : - Message() + MsgReportAvailableChannelOrFeatures(const QStringList& renameFrom, const QStringList& renameTo) : + Message(), + m_renameFrom(renameFrom), + m_renameTo(renameTo) {} }; @@ -212,7 +220,8 @@ private: QThread *m_thread; GS232ControllerWorker *m_worker; GS232ControllerSettings m_settings; - QHash m_availableChannelOrFeatures; + AvailableChannelOrFeatureList m_availableChannelOrFeatures; + AvailableChannelOrFeatureHandler m_availableChannelOrFeatureHandler; QObject *m_selectedPipe; QTimer m_timer; @@ -229,17 +238,11 @@ private: void applySettings(const GS232ControllerSettings& settings, const QList& settingsKeys, bool force = false); void webapiReverseSendSettings(const QList& featureSettingsKeys, const GS232ControllerSettings& settings, bool force); void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); - void scanAvailableChannelsAndFeatures(); - void notifyUpdate(); - void registerPipe(QObject *object); + void notifyUpdate(const QStringList& renameFrom, const QStringList& renameTo); private slots: void networkManagerFinished(QNetworkReply *reply); - void handleFeatureAdded(int featureSetIndex, Feature *feature); - void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); - void handleFeatureRemoved(int featureSetIndex, Feature *feature); - void handleChannelRemoved(int deviceSetIndex, ChannelAPI *feature); - void handleMessagePipeToBeDeleted(int reason, QObject* object); + void channelsOrFeaturesChanged(const QStringList& renameFrom, const QStringList& renameTo); void handlePipeMessageQueue(MessageQueue* messageQueue); void scanSerialPorts(); }; diff --git a/plugins/feature/gs232controller/gs232controllergui.cpp b/plugins/feature/gs232controller/gs232controllergui.cpp index 8f04a8ef2..6c9477310 100644 --- a/plugins/feature/gs232controller/gs232controllergui.cpp +++ b/plugins/feature/gs232controller/gs232controllergui.cpp @@ -51,7 +51,7 @@ void GS232ControllerGUI::resetToDefaults() { m_settings.resetToDefaults(); displaySettings(); - applySettings(true); + applyAllSettings(); } QByteArray GS232ControllerGUI::serialize() const @@ -65,7 +65,7 @@ bool GS232ControllerGUI::deserialize(const QByteArray& data) { m_feature->setWorkspaceIndex(m_settings.m_workspaceIndex); displaySettings(); - applySettings(true); + applyAllSettings(); return true; } else @@ -121,9 +121,7 @@ void GS232ControllerGUI::displayToAzEl(float coord1, float coord2) m_settings.m_azimuth = coord1; m_settings.m_elevation = coord2; } - m_settingsKeys.append("azimuth"); - m_settingsKeys.append("elevation"); - applySettings(); + applySettings({"azimuth", "elevation"}); } bool GS232ControllerGUI::handleMessage(const Message& message) @@ -149,7 +147,7 @@ bool GS232ControllerGUI::handleMessage(const Message& message) { GS232Controller::MsgReportAvailableChannelOrFeatures& report = (GS232Controller::MsgReportAvailableChannelOrFeatures&) message; - updatePipeList(report.getItems()); + updatePipeList(report.getItems(), report.getRenameFrom(), report.getRenameTo()); return true; } else if (GS232ControllerReport::MsgReportAzAl::match(message)) @@ -206,7 +204,7 @@ void GS232ControllerGUI::onWidgetRolled(QWidget* widget, bool rollDown) (void) rollDown; getRollupContents()->saveState(m_rollupState); - applySettings(); + applySetting("rollupState"); } GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) : @@ -260,7 +258,7 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu connect(&m_inputTimer, &QTimer::timeout, this, &GS232ControllerGUI::checkInputController); displaySettings(); - applySettings(true); + applyAllSettings(); makeUIConnections(); // Get pre-existing pipes @@ -408,8 +406,7 @@ void GS232ControllerGUI::on_inputController_currentIndexChanged(int index) if (index >= 0) { m_settings.m_inputController = ui->inputController->currentText(); - m_settingsKeys.append("inputController"); - applySettings(); + applySetting("inputController"); updateInputController(); } } @@ -425,28 +422,24 @@ void GS232ControllerGUI::on_highSensitivity_clicked(bool checked) { m_settings.m_highSensitivity = checked; ui->highSensitivity->setText(checked ? "H" : "L"); - m_settingsKeys.append("highSensitivity"); - applySettings(); + applySetting("highSensitivity"); } void GS232ControllerGUI::on_enableTargetControl_clicked(bool checked) { m_settings.m_targetControlEnabled = checked; - m_settingsKeys.append("targetControlEnabled"); - applySettings(); + applySetting("targetControlEnabled"); } void GS232ControllerGUI::on_enableOffsetControl_clicked(bool checked) { m_settings.m_offsetControlEnabled = checked; - m_settingsKeys.append("offsetControlEnabled"); - applySettings(); + applySetting("offsetControlEnabled"); } void GS232ControllerGUI::inputConfigurationComplete() { - m_settingsKeys.append("inputControllerSettings"); - applySettings(); + applySetting("inputControllerSettings"); } GS232ControllerGUI::~GS232ControllerGUI() @@ -546,57 +539,50 @@ void GS232ControllerGUI::updateSerialPortList(const QStringList& serialPorts) ui->serialPort->blockSignals(false); } -void GS232ControllerGUI::updatePipeList(const QList& sources) +void GS232ControllerGUI::updatePipeList(const AvailableChannelOrFeatureList& sources, const QStringList& renameFrom, const QStringList& renameTo) { - QString currentText = ui->sources->currentText(); - QString newText; + // Update source settting if it has been renamed + if (renameFrom.contains(m_settings.m_source)) + { + m_settings.m_source = renameTo[renameFrom.indexOf(m_settings.m_source)]; + applySetting("source"); + } + + int prevIdx = ui->sources->currentIndex(); ui->sources->blockSignals(true); ui->sources->clear(); - for (const auto& source : sources) - { - QString name = tr("%1%2:%3 %4") - .arg(source.m_kind) - .arg(source.m_superIndex) - .arg(source.m_index) - .arg(source.m_type); - ui->sources->addItem(name); + for (const auto& source : sources) { + ui->sources->addItem(source.getLongId()); } - int index = ui->sources->findText(m_settings.m_source); - ui->sources->setCurrentIndex(index); - - if (index < 0) // current source is not found + // Select current setting, if it exists + // If not, and no prior setting, make sure nothing selected, as channel/feature may be created later on + // If not found and something was previously selected, clear the setting, as probably deleted + int idx = ui->sources->findText(m_settings.m_source); + if (idx >= 0) + { + ui->sources->setCurrentIndex(idx); + } + else if (prevIdx == -1) + { + ui->sources->setCurrentIndex(-1); + } + else { m_settings.m_source = ""; + applySetting("source"); ui->targetName->setText(""); - m_settingsKeys.append("source"); - applySettings(); } - // if (currentText.isEmpty()) - // { - // // Source feature may be loaded after this, so may not have existed when - // // displaySettings was called - // if (sources.size() > 0) { - // ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source)); - // } - // } - // else - // { - // ui->sources->setCurrentIndex(ui->sources->findText(currentText)); - // } - ui->sources->blockSignals(false); - // QString newText = ui->sources->currentText(); - - // if (currentText != newText) - // { - // m_settings.m_source = newText; - // ui->targetName->setText(""); - // applySettings(); - // } + // If no current settting, select first available + if (m_settings.m_source.isEmpty() && (ui->sources->count() > 0)) + { + ui->sources->setCurrentIndex(0); + on_sources_currentTextChanged(ui->sources->currentText()); + } } void GS232ControllerGUI::onMenuDialogCalled(const QPoint &p) @@ -626,15 +612,17 @@ void GS232ControllerGUI::onMenuDialogCalled(const QPoint &p) setTitle(m_settings.m_title); setTitleColor(m_settings.m_rgbColor); - m_settingsKeys.append("title"); - m_settingsKeys.append("rgbColor"); - m_settingsKeys.append("useReverseAPI"); - m_settingsKeys.append("reverseAPIAddress"); - m_settingsKeys.append("reverseAPIPort"); - m_settingsKeys.append("reverseAPIFeatureSetIndex"); - m_settingsKeys.append("reverseAPIFeatureIndex"); + QList settingsKeys({ + "rgbColor", + "title", + "useReverseAPI", + "reverseAPIAddress", + "reverseAPIPort", + "reverseAPIDeviceIndex", + "reverseAPIChannelIndex" + }); - applySettings(); + applySettings(settingsKeys); } resetContextMenuType(); @@ -704,15 +692,13 @@ void GS232ControllerGUI::on_protocol_currentIndexChanged(int index) { m_settings.m_protocol = (GS232ControllerSettings::Protocol)index; setProtocol(m_settings.m_protocol); - m_settingsKeys.append("protocol"); - applySettings(); + applySetting("protocol"); } void GS232ControllerGUI::on_connection_currentIndexChanged(int index) { m_settings.m_connection = (GS232ControllerSettings::Connection)index; - m_settingsKeys.append("connection"); - applySettings(); + applySetting("connection"); updateConnectionWidgets(); } @@ -720,30 +706,26 @@ void GS232ControllerGUI::on_serialPort_currentIndexChanged(int index) { (void) index; m_settings.m_serialPort = ui->serialPort->currentText(); - m_settingsKeys.append("serialPort"); - applySettings(); + applySetting("serialPort"); } void GS232ControllerGUI::on_baudRate_currentIndexChanged(int index) { (void) index; m_settings.m_baudRate = ui->baudRate->currentText().toInt(); - m_settingsKeys.append("baudRate"); - applySettings(); + applySetting("baudRate"); } void GS232ControllerGUI::on_host_editingFinished() { m_settings.m_host = ui->host->text(); - m_settingsKeys.append("host"); - applySettings(); + applySetting("host"); } void GS232ControllerGUI::on_port_valueChanged(int value) { m_settings.m_port = value; - m_settingsKeys.append("port"); - applySettings(); + applySetting("port"); } void GS232ControllerGUI::on_coord1_valueChanged(double value) @@ -770,8 +752,7 @@ void GS232ControllerGUI::on_azimuthOffset_valueChanged(double value) m_inputAzOffset = value; } m_settings.m_azimuthOffset = (float) value; - m_settingsKeys.append("azimuthOffset"); - applySettings(); + applySetting("azimuthOffset"); } void GS232ControllerGUI::on_elevationOffset_valueChanged(double value) @@ -780,58 +761,50 @@ void GS232ControllerGUI::on_elevationOffset_valueChanged(double value) m_inputElOffset = value; } m_settings.m_elevationOffset = (float) value; - m_settingsKeys.append("elevationOffset"); - applySettings(); + applySetting("elevationOffset"); } void GS232ControllerGUI::on_azimuthMin_valueChanged(int value) { m_settings.m_azimuthMin = value; - m_settingsKeys.append("azimuthMin"); - applySettings(); + applySetting("azimuthMin"); } void GS232ControllerGUI::on_azimuthMax_valueChanged(int value) { m_settings.m_azimuthMax = value; - m_settingsKeys.append("azimuthMax"); - applySettings(); + applySetting("azimuthMax"); } void GS232ControllerGUI::on_elevationMin_valueChanged(int value) { m_settings.m_elevationMin = value; - m_settingsKeys.append("elevationMin"); - applySettings(); + applySetting("elevationMin"); } void GS232ControllerGUI::on_elevationMax_valueChanged(int value) { m_settings.m_elevationMax = value; - m_settingsKeys.append("elevationMax"); - applySettings(); + applySetting("elevationMax"); } void GS232ControllerGUI::on_tolerance_valueChanged(double value) { m_settings.m_tolerance = value; - m_settingsKeys.append("tolerance"); - applySettings(); + applySetting("tolerance"); } void GS232ControllerGUI::on_precision_valueChanged(int value) { m_settings.m_precision = value; setPrecision(); - m_settingsKeys.append("precision"); - applySettings(); + applySetting("precision"); } void GS232ControllerGUI::on_coordinates_currentIndexChanged(int index) { m_settings.m_coordinates = (GS232ControllerSettings::Coordinates)index; - m_settingsKeys.append("coordinates"); - applySettings(); + applySetting("coordinates"); float coord1, coord2; azElToDisplay(m_settings.m_azimuth, m_settings.m_elevation, coord1, coord2); @@ -886,8 +859,7 @@ void GS232ControllerGUI::on_track_stateChanged(int state) ui->targetName->setText(""); } - m_settingsKeys.append("track"); - applySettings(); + applySetting("track"); } void GS232ControllerGUI::on_sources_currentTextChanged(const QString& text) @@ -895,36 +867,31 @@ void GS232ControllerGUI::on_sources_currentTextChanged(const QString& text) qDebug("GS232ControllerGUI::on_sources_currentTextChanged: %s", qPrintable(text)); m_settings.m_source = text; ui->targetName->setText(""); - m_settingsKeys.append("source"); - applySettings(); + applySetting("source"); } void GS232ControllerGUI::on_dfmTrack_clicked(bool checked) { m_settings.m_dfmTrackOn = checked; - m_settingsKeys.append("dfmTrackOn"); - applySettings(); + applySetting("dfmTrackOn"); } void GS232ControllerGUI::on_dfmLubePumps_clicked(bool checked) { m_settings.m_dfmLubePumpsOn = checked; - m_settingsKeys.append("dfmLubePumpsOn"); - applySettings(); + applySetting("dfmLubePumpsOn"); } void GS232ControllerGUI::on_dfmBrakes_clicked(bool checked) { m_settings.m_dfmBrakesOn = checked; - m_settingsKeys.append("dfmBrakesOn"); - applySettings(); + applySetting("dfmBrakesOn"); } void GS232ControllerGUI::on_dfmDrives_clicked(bool checked) { m_settings.m_dfmDrivesOn = checked; - m_settingsKeys.append("dfmDrivesOn"); - applySettings(); + applySetting("dfmDrivesOn"); } void GS232ControllerGUI::on_dfmShowStatus_clicked() @@ -989,17 +956,28 @@ void GS232ControllerGUI::updateStatus() } } -void GS232ControllerGUI::applySettings(bool force) +void GS232ControllerGUI::applySetting(const QString& settingsKey) { + applySettings({settingsKey}); +} + +void GS232ControllerGUI::applySettings(const QStringList& settingsKeys, bool force) +{ + m_settingsKeys.append(settingsKeys); if (m_doApplySettings) { GS232Controller::MsgConfigureGS232Controller* message = GS232Controller::MsgConfigureGS232Controller::create(m_settings, m_settingsKeys, force); m_gs232Controller->getInputMessageQueue()->push(message); + m_settingsKeys.clear(); } - - m_settingsKeys.clear(); } +void GS232ControllerGUI::applyAllSettings() +{ + applySettings(QStringList(), true); +} + + void GS232ControllerGUI::makeUIConnections() { QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &GS232ControllerGUI::on_startStop_toggled); diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index 6c89f29eb..4a7a36347 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -85,12 +85,14 @@ private: virtual ~GS232ControllerGUI(); void blockApplySettings(bool block); - void applySettings(bool force = false); + void applySetting(const QString& settingsKey); + void applySettings(const QStringList& settingsKeys, bool force = false); + void applyAllSettings(); void displaySettings(); void setProtocol(GS232ControllerSettings::Protocol protocol); void setPrecision(); void updateConnectionWidgets(); - void updatePipeList(const QList& sources); + void updatePipeList(const AvailableChannelOrFeatureList& sources, const QStringList& renameFrom, const QStringList& renameTo); void updateSerialPortList(); void updateSerialPortList(const QStringList& serialPorts); bool handleMessage(const Message& message); diff --git a/plugins/feature/gs232controller/gs232controllersettings.cpp b/plugins/feature/gs232controller/gs232controllersettings.cpp index 4f11472cf..cfd169815 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.cpp +++ b/plugins/feature/gs232controller/gs232controllersettings.cpp @@ -2,7 +2,7 @@ // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // // written by Christian Daniel // // Copyright (C) 2015-2017, 2019-2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2020-2021, 2023 Jon Beniston, M7RCE // +// Copyright (C) 2020-2021, 2024 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 // @@ -26,16 +26,10 @@ #include "gs232controllersettings.h" #include "inputcontrollersettings.h" -const QStringList GS232ControllerSettings::m_pipeTypes = { - QStringLiteral("ADSBDemod"), - QStringLiteral("Map"), - QStringLiteral("StarTracker"), - QStringLiteral("SatelliteTracker") -}; - const QStringList GS232ControllerSettings::m_pipeURIs = { QStringLiteral("sdrangel.channel.adsbdemod"), QStringLiteral("sdrangel.feature.map"), + QStringLiteral("sdrangel.feature.skymap"), QStringLiteral("sdrangel.feature.startracker"), QStringLiteral("sdrangel.feature.satellitetracker") }; diff --git a/plugins/feature/gs232controller/gs232controllersettings.h b/plugins/feature/gs232controller/gs232controllersettings.h index 8b61dd478..9d6e3b81b 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.h +++ b/plugins/feature/gs232controller/gs232controllersettings.h @@ -2,7 +2,7 @@ // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // // written by Christian Daniel // // Copyright (C) 2015-2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2020-2021, 2023 Jon Beniston, M7RCE // +// Copyright (C) 2020-2021, 2024 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 // @@ -31,21 +31,6 @@ class Serializable; struct GS232ControllerSettings { - struct AvailableChannelOrFeature - { - QString m_kind; //!< "R" for channel, "F" for feature - int m_superIndex; - int m_index; - QString m_type; - - AvailableChannelOrFeature() = default; - AvailableChannelOrFeature(const AvailableChannelOrFeature&) = default; - AvailableChannelOrFeature& operator=(const AvailableChannelOrFeature&) = default; - bool operator==(const AvailableChannelOrFeature& a) const { - return (m_kind == a.m_kind) && (m_superIndex == a.m_superIndex) && (m_index == a.m_index) && (m_type == a.m_type); - } - }; - float m_azimuth; float m_elevation; QString m_serialPort; @@ -96,7 +81,6 @@ struct GS232ControllerSettings void applySettings(const QStringList& settingsKeys, const GS232ControllerSettings& settings); QString getDebugString(const QStringList& settingsKeys, bool force=false) const; - static const QStringList m_pipeTypes; static const QStringList m_pipeURIs; }; diff --git a/plugins/feature/gs232controller/gs232controllerworker.cpp b/plugins/feature/gs232controller/gs232controllerworker.cpp index c61c8a4db..10fb93d21 100644 --- a/plugins/feature/gs232controller/gs232controllerworker.cpp +++ b/plugins/feature/gs232controller/gs232controllerworker.cpp @@ -25,6 +25,11 @@ #include #include +#include "maincore.h" +#include "util/astronomy.h" + +#include "SWGTargetAzimuthElevation.h" + #include "gs232controller.h" #include "gs232controllerworker.h" #include "gs232controllerreport.h" @@ -32,7 +37,8 @@ MESSAGE_CLASS_DEFINITION(GS232ControllerWorker::MsgConfigureGS232ControllerWorker, Message) MESSAGE_CLASS_DEFINITION(GS232ControllerReport::MsgReportAzAl, Message) -GS232ControllerWorker::GS232ControllerWorker() : +GS232ControllerWorker::GS232ControllerWorker(GS232Controller *controller) : + m_controller(controller), m_msgQueueToFeature(nullptr), m_device(nullptr), m_serialPort(this), @@ -193,6 +199,8 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting { setAzimuth(azimuth); } + + sendToSkyMap(azimuth, elevation); } } @@ -280,3 +288,18 @@ void GS232ControllerWorker::update() } } +void GS232ControllerWorker::sendToSkyMap(float azimuth, float elevation) +{ + QList targetPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(m_controller, "target", targetPipes); + + for (const auto& pipe : targetPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString("Rotator")); + swgTarget->setAzimuth(azimuth); + swgTarget->setElevation(elevation); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(m_controller, swgTarget)); + } +} diff --git a/plugins/feature/gs232controller/gs232controllerworker.h b/plugins/feature/gs232controller/gs232controllerworker.h index 88987f2da..82a225cae 100644 --- a/plugins/feature/gs232controller/gs232controllerworker.h +++ b/plugins/feature/gs232controller/gs232controllerworker.h @@ -32,6 +32,8 @@ #include "gs232controllersettings.h" #include "controllerprotocol.h" +class GS232Controller; + class GS232ControllerWorker : public QObject { Q_OBJECT @@ -62,7 +64,7 @@ public: { } }; - GS232ControllerWorker(); + GS232ControllerWorker(GS232Controller *controller); ~GS232ControllerWorker(); void startWork(); void stopWork(); @@ -72,6 +74,7 @@ public: private: + GS232Controller *m_controller; MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication MessageQueue *m_msgQueueToFeature; //!< Queue to report channel change to main feature object GS232ControllerSettings m_settings; @@ -92,6 +95,7 @@ private: QIODevice *openSocket(const GS232ControllerSettings& settings); void setAzimuth(float azimuth); void setAzimuthElevation(float azimuth, float elevation); + void sendToSkyMap(float azimuth, float elevation); private slots: void handleInputMessages(); diff --git a/plugins/feature/gs232controller/readme.md b/plugins/feature/gs232controller/readme.md index f5106599d..e066512f8 100644 --- a/plugins/feature/gs232controller/readme.md +++ b/plugins/feature/gs232controller/readme.md @@ -185,8 +185,8 @@ The controller uses the 'P' and 'p' commands to set and get azimuth and elevatio Full details of the API can be found in the Swagger documentation. Here is a quick example of how to set the azimuth and elevation from the command line: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "GS232Controller", "GS232ControllerSettings": { "azimuth": 180, "elevation": 45 }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "GS232Controller", "GS232ControllerSettings": { "azimuth": 180, "elevation": 45 }}' To start sending commands to the rotator: - curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/run" + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/feature/0/run" diff --git a/plugins/feature/pertester/readme.md b/plugins/feature/pertester/readme.md index b6e4ad87b..73db96bca 100644 --- a/plugins/feature/pertester/readme.md +++ b/plugins/feature/pertester/readme.md @@ -97,8 +97,8 @@ The statistics fields display the statistics for the current test: Full details of the API can be found in the Swagger documentation. Here is a quick example of how to set the azimuth and elevation from the command line: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "PERTester", "PERTesterSettings": { "packetCount": 100 }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "PERTester", "PERTesterSettings": { "packetCount": 100 }}' To start sending the test: - curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/run" + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/feature/0/run" diff --git a/plugins/feature/radiosonde/radiosonde.cpp b/plugins/feature/radiosonde/radiosonde.cpp index 8dc985677..0fcafa60b 100644 --- a/plugins/feature/radiosonde/radiosonde.cpp +++ b/plugins/feature/radiosonde/radiosonde.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2021-2022 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -41,7 +41,8 @@ const char* const Radiosonde::m_featureIdURI = "sdrangel.feature.radiosonde"; const char* const Radiosonde::m_featureId = "Radiosonde"; Radiosonde::Radiosonde(WebAPIAdapterInterface *webAPIAdapterInterface) : - Feature(m_featureIdURI, webAPIAdapterInterface) + Feature(m_featureIdURI, webAPIAdapterInterface), + m_availableChannelHandler({"sdrangel.channel.radiosondedemod"}, QStringList{"radiosonde"}) { qDebug("Radiosonde::Radiosonde: webAPIAdapterInterface: %p", webAPIAdapterInterface); setObjectName(m_featureId); @@ -54,22 +55,22 @@ Radiosonde::Radiosonde(WebAPIAdapterInterface *webAPIAdapterInterface) : this, &Radiosonde::networkManagerFinished ); - scanAvailableChannels(); + QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &Radiosonde::handleChannelAdded - ); + &Radiosonde::handleChannelMessageQueue); + m_availableChannelHandler.scanAvailableChannelsAndFeatures(); } Radiosonde::~Radiosonde() { QObject::disconnect( - MainCore::instance(), - &MainCore::channelAdded, + &m_availableChannelHandler, + &AvailableChannelOrFeatureHandler::messageEnqueued, this, - &Radiosonde::handleChannelAdded + &Radiosonde::handleChannelMessageQueue ); QObject::disconnect( m_networkManager, @@ -362,90 +363,6 @@ void Radiosonde::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } -void Radiosonde::scanAvailableChannels() -{ - MainCore *mainCore = MainCore::instance(); - MessagePipes& messagePipes = mainCore->getMessagePipes(); - std::vector& deviceSets = mainCore->getDeviceSets(); - m_availableChannels.clear(); - - for (const auto& deviceSet : deviceSets) - { - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine) - { - for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) - { - ChannelAPI *channel = deviceSet->getChannelAt(chi); - - if ((channel->getURI() == "sdrangel.channel.radiosondedemod") && !m_availableChannels.contains(channel)) - { - qDebug("Radiosonde::scanAvailableChannels: register %d:%d (%p)", deviceSet->getIndex(), chi, channel); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "radiosonde"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &Radiosonde::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } - } - } -} - -void Radiosonde::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) -{ - qDebug("Radiosonde::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - std::vector& deviceSets = MainCore::instance()->getDeviceSets(); - DeviceSet *deviceSet = deviceSets[deviceSetIndex]; - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine && (channel->getURI() == "sdrangel.channel.radiosondedemod")) - { - if (!m_availableChannels.contains(channel)) - { - MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "radiosonde"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &Radiosonde::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } -} - -void Radiosonde::handleMessagePipeToBeDeleted(int reason, QObject* object) -{ - if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) - { - qDebug("Radiosonde::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } -} - void Radiosonde::handleChannelMessageQueue(MessageQueue* messageQueue) { Message* message; diff --git a/plugins/feature/radiosonde/radiosonde.h b/plugins/feature/radiosonde/radiosonde.h index af3f1d676..a5a99f602 100644 --- a/plugins/feature/radiosonde/radiosonde.h +++ b/plugins/feature/radiosonde/radiosonde.h @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // -// Copyright (C) 2021-2022 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -25,6 +25,7 @@ #include "feature/feature.h" #include "util/message.h" +#include "availablechannelorfeaturehandler.h" #include "radiosondesettings.h" @@ -101,7 +102,8 @@ public: private: RadiosondeSettings m_settings; - QSet m_availableChannels; + AvailableChannelOrFeatureHandler m_availableChannelHandler; + AvailableChannelOrFeatureList m_availableChannels; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -110,12 +112,9 @@ private: void stop(); void applySettings(const RadiosondeSettings& settings, const QList& settingsKeys, bool force = false); void webapiReverseSendSettings(const QList& featureSettingsKeys, const RadiosondeSettings& settings, bool force); - void scanAvailableChannels(); private slots: void networkManagerFinished(QNetworkReply *reply); - void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); - void handleMessagePipeToBeDeleted(int reason, QObject* object); void handleChannelMessageQueue(MessageQueue* messageQueue); }; diff --git a/plugins/feature/satellitetracker/readme.md b/plugins/feature/satellitetracker/readme.md index 0348f697c..6dc1b5cc7 100644 --- a/plugins/feature/satellitetracker/readme.md +++ b/plugins/feature/satellitetracker/readme.md @@ -216,12 +216,12 @@ Icons are by Freepik from Flaticon https://www.flaticon.com/ Full details of the API can be found in the Swagger documentation. Here is a quick example of how to set the satellites to track: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "satellites": [ "NOAA 15", "NOAA 19" ] }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "satellites": [ "NOAA 15", "NOAA 19" ] }}' And how to set the target: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "target": "NOAA 15" }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "target": "NOAA 15" }}' Or, to set the device settings: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "deviceSettings": [ { "satellite": "ISS", "deviceSettings": [ { "deviceSet": "R0", "doppler": [0], "frequency": 0, "presetDescription": Sat", "presetFrequency": 145.825, "presetGroup": "ISS Digi", "startOnAOS": 1, "startStopFileSinks": 1, "stopOnLOS": 1}] } ] }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "SatelliteTracker", "SatelliteTrackerSettings": { "deviceSettings": [ { "satellite": "ISS", "deviceSettings": [ { "deviceSet": "R0", "doppler": [0], "frequency": 0, "presetDescription": Sat", "presetFrequency": 145.825, "presetGroup": "ISS Digi", "startOnAOS": 1, "startStopFileSinks": 1, "stopOnLOS": 1}] } ] }}' diff --git a/plugins/feature/skymap/CMakeLists.txt b/plugins/feature/skymap/CMakeLists.txt new file mode 100644 index 000000000..5d83d879f --- /dev/null +++ b/plugins/feature/skymap/CMakeLists.txt @@ -0,0 +1,92 @@ +project(skymap) + +set(skymap_SOURCES + skymap.cpp + skymapsettings.cpp + skymapplugin.cpp + skymapwebapiadapter.cpp + webserver.cpp +) + +set(skymap_HEADERS + skymap.h + skymapsettings.h + skymapplugin.h + skymapreport.h + skymapwebapiadapter.h + webserver.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${Qt${QT_DEFAULT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS} +) + +if(NOT SERVER_MODE) + set(skymap_SOURCES + ${skymap_SOURCES} + skymapgui.cpp + skymapgui.ui + skymapsettingsdialog.cpp + skymapsettingsdialog.ui + websocketserver.cpp + skymap.qrc + webinterface.cpp + wtml.cpp + webview.cpp + icons.qrc + ) + set(skymap_HEADERS + ${skymap_HEADERS} + skymapgui.h + skymapsettingsdialog.h + skymapmodel.h + skymapitem.h + websocketserver.h + skymaptileserver.h + webinterface.h + wtml.h + webview.h + ) + + set(TARGET_NAME featureskymap) + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) + + if(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngineCore_FOUND) + set(TARGET_LIB "Qt::Widgets" Qt::Positioning Qt::Location Qt::WebEngineCore Qt::WebEngineWidgets) + elseif(Qt${QT_DEFAULT_MAJOR_VERSION}WebEngine_FOUND) + set(TARGET_LIB "Qt::Widgets" Qt::Positioning Qt::Location Qt::WebEngine Qt::WebEngineCore Qt::WebEngineWidgets) + else() + set(TARGET_LIB "Qt::Widgets" Qt::Positioning Qt::Location) + endif() +else() + set(TARGET_NAME featureskymapsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${skymap_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) + +if(WIN32) + # Run deployqt for QtQuick etc + include(DeployQt) + windeployqt(${TARGET_NAME} ${SDRANGEL_BINARY_BIN_DIR} ${PROJECT_SOURCE_DIR}/skymap) +endif() + +# Install debug symbols +if (WIN32) + install(FILES $ CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} ) +endif() diff --git a/plugins/feature/skymap/html/aladin.html b/plugins/feature/skymap/html/aladin.html new file mode 100644 index 000000000..dbba8975b --- /dev/null +++ b/plugins/feature/skymap/html/aladin.html @@ -0,0 +1,166 @@ + + + + SDRangel Aladin + + + + + +
+ + + + + + diff --git a/plugins/feature/skymap/html/esasky.html b/plugins/feature/skymap/html/esasky.html new file mode 100644 index 000000000..2161e4818 --- /dev/null +++ b/plugins/feature/skymap/html/esasky.html @@ -0,0 +1,181 @@ + + + + SDRangel ESASky + + + + + + +
+ +
+ + + diff --git a/plugins/feature/skymap/html/wwt.html b/plugins/feature/skymap/html/wwt.html new file mode 100644 index 000000000..5d8640d67 --- /dev/null +++ b/plugins/feature/skymap/html/wwt.html @@ -0,0 +1,828 @@ + + + + SDRangel WWT + + + + + + + + + + + +
+ + + + diff --git a/plugins/feature/skymap/icons.qrc b/plugins/feature/skymap/icons.qrc new file mode 100644 index 000000000..4ef775a72 --- /dev/null +++ b/plugins/feature/skymap/icons.qrc @@ -0,0 +1,6 @@ + + + icons/constellation.png + icons/reticle.png + + diff --git a/plugins/feature/skymap/icons/constellation.png b/plugins/feature/skymap/icons/constellation.png new file mode 100644 index 000000000..b9a693ce5 Binary files /dev/null and b/plugins/feature/skymap/icons/constellation.png differ diff --git a/plugins/feature/skymap/icons/reticle.png b/plugins/feature/skymap/icons/reticle.png new file mode 100644 index 000000000..6bd900403 Binary files /dev/null and b/plugins/feature/skymap/icons/reticle.png differ diff --git a/plugins/feature/skymap/readme.md b/plugins/feature/skymap/readme.md new file mode 100644 index 000000000..b1f16d390 --- /dev/null +++ b/plugins/feature/skymap/readme.md @@ -0,0 +1,141 @@ +

Sky Map Feature Plugin

+ +

Introduction

+ +The Sky Map Feature provides visualization of the sky in multiple wavelengths (radio, IR, optical, UV, X-Ray, gamma). +Multiple Sky Maps are supported, including the [World Wide Telescope](https://www.worldwidetelescope.org/), [ESASky](https://www.esa.int/About_Us/ESAC/Explore_the_cosmos_with_ESASky) and [Aladin Lite](https://aladin.cds.unistra.fr/). + +The Rotator Controller and Star Tracker plugins can track the position viewed in the Sky Map. The Sky Map can also be set to track coordinates from the Star Tracker, Satellite Tracker, Rotator Controller or Map. + +![Sky Map feature WWT](../../../doc/img/SkyMap_wwt.png) + +With the ESASky map, a host of astronomical data is available from JWST, Hubble, Gaia, Herschel and others, including images, spectra and publications: + +![Sky Map feature ESASky](../../../doc/img/SkyMap_ESASky.png) + +

Interface

+ +![Sky Map feature plugin GUI](../../../doc/img/SkyMap_settings.png) + +

1: Find

+ +Enter an astronomical object name and press enter to centre the sky map on that object. + +You can also enter J2000 RA and Dec coordinates, in either HMS/DMS or decimal: + +* 12 05 12.23 +17 06 21.0 +* 12 05 12 17 06 21 +* 12:05:12.23 -17:06:21.20 +* 12h05m12.23s +17d06m21.10s +* 107.1324 -34.233 + +Note that the supported object names depend on the chosen map (2). + +

2: Map Type

+ +Allows you to select the sky map: + +* WWT - World Wide Telescope +* ESASky +* Aladin + +Each map provides different features, image and data sets. + +

3: Background Image Set

+ +For WWT and Aladin, this sets the background image set the sky map will display. For ESASky, this must be set within the ESASky GUI (using the Manage Skies button), as this can use multiple image sets. + +Image sets are available for a variety of wavelengths (radio, IR, optical, UV, X-Ray, gamma) from a number of different surveys. + +

4: Projection

+ +For World Wide Telescope: + +* Sky - Views the sky from a position on Earth, +* Solar System - Views the Solar System, with the ability to show orbits, +* Planet - Views one of the planets or major moons. + +For Aladin: + +* SIN - [orthographic](https://en.wikipedia.org/wiki/Orthographic_map_projection), +* AIT - [Hammer-Aitoff](https://en.wikipedia.org/wiki/Hammer_projection), +* MOL - [Mollweide](https://en.wikipedia.org/wiki/Mollweide_projection), +* MER - [Mercator](https://en.wikipedia.org/wiki/Mercator_projection), +* ARC - zenithal/azimuthal equidistant, +* TAN - [gnomonic](https://en.wikipedia.org/wiki/Gnomonic_projection), +* HPX - [HEALPix](https://en.wikipedia.org/wiki/HEALPix). + +This option is not available for ESASky, which is currently fixed to orthographic. + +See [List of map projections](https://en.wikipedia.org/wiki/List_of_map_projections). + +

5: Display Names

+ +For WWT, when checked, displays names of constellations and Ecliptic text (when the constellations and Ecliptic are visible). + +

6: Display Constellations

+ +For WWT, this option enables the display of constellations. How the constellations are drawn can be customised in the Display Settings dialog (12). + +

7: Display gird

+ +When checked, displays a coordinate grid. + +For WWT, Ecliptic, Alt/Az, Equatorial and Galactic grids can be displayed. These can be selected in the Display Settings dialog (12). + +For ESASky and Aladin, the grid will be Equatorial or Galactic, depending on the coordinate mode selected. + +

8: Display reticle

+ +When checked, displays a reticle (cross hair) at the centre of the view. Coordinates for the reticle are displayed in the status bar in the bottom of the window. + +

9: Display antenna field-of-view

+ +When checked, displays the antenna field-of-view. The antenna beamwidth can be set in the Display Settings dialog (12) or from a Star Tracker source (11). + +

10: Track

+ +When checked, the centre of view will track the coordinates received from the selected Source plugin (11). + +

11: Source

+ +Select a Star Tracker, Rotator Controller, Satellite Tracker or Map plugin to read viewing coordinates from. + +* When a Star Tracker is selected, target RA/Dec, observation position, antenna beamwith and date/time will be read from the selected plugin. +* For other plugin types, Alt/El will be read and other parameters are taken from the the Display Settings dialog (12). + +

12: Display settings

+ +When clicked, opens the Display Settings dialog. The Display Settings dialog allows the user to set: + +* Observation location (latitude and longitude in degreees). +* Antenna beamwidth in degrees. +* Settings for WWT, such as how the constellations are drawn, what grids are displayed and how the Solar System view appears. + +

Sky Map Controls

+ +* Click and drag using the left mouse button to rotate through right ascension or declination. +* Use the mouse wheel to zoom in and out. +* In WWT, right click to display information about the nearest astronomical object. The object will be circled and a popup information window will appear with links to relevant astronomical databases (ADS, SIMBAD, NED, VizieR). +The popup window can be moved by left clicking and dragging it. +* In ESASky, right click to display a popup window, with links to various astronomical databases (SIMBAD, NED, VizieR) for the corresponding coordinates. +* In Aladin, right click to display a popup menu. Use the "What is this?" menu to display a window with a link to the CDS astronomical database. + +ESASky and Aladin are able to overlay catalog data: + +* In ESASky, zoom in to the area of interest, then press the "Explore catalog data for this region" button. A window will appear showing available catalogs. Left click and boxes will be overlaid on the map for each catalog entry. The data is also displayed in tabular form. You can left click on a box to view its data in the table. +* In Aladin, zoom in to the areae of interest, then press the "Manage layers" button. In the popup window, select one or more of the available catalogs, or press Add catalogue to add a new one. Boxes will be overlaid on the map for each catalog entry. Left click on a box to display the data for it in tabular form. + +

Attribution

+ +Constellation icons created by Freepik - https://www.flaticon.com + +

API

+ +Full details of the API can be found in the Swagger documentation. Here is a quick example of how to centre the sky map on an object from the command line: + + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/feature/0/actions" -d '{"featureType": "SkyMap", "SkyMapActions": { "find": "polaris" }}' + +And to centre the sky map at a particular RA and dec (Not for WWT): + + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/feature/0/actions" -d '{"featureType": "SkyMap", "SkyMapActions": { "find": "18 36 56 +38 47 01" }}' diff --git a/plugins/feature/skymap/skymap.cpp b/plugins/feature/skymap/skymap.cpp new file mode 100644 index 000000000..a2bba969e --- /dev/null +++ b/plugins/feature/skymap/skymap.cpp @@ -0,0 +1,510 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // +// Copyright (C) 2021-2023 Edouard Griffiths, F4EXB // +// Copyright (C) 2022 Jiří Pinkava // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "SWGFeatureSettings.h" +#include "SWGFeatureReport.h" +#include "SWGFeatureActions.h" +#include "SWGDeviceState.h" + +#include "dsp/dspengine.h" + +#include "device/deviceset.h" +#include "channel/channelapi.h" +#include "feature/featureset.h" +#include "settings/serializable.h" +#include "maincore.h" +#include "skymap.h" + +MESSAGE_CLASS_DEFINITION(SkyMap::MsgConfigureSkyMap, Message) +MESSAGE_CLASS_DEFINITION(SkyMap::MsgFind, Message) +MESSAGE_CLASS_DEFINITION(SkyMap::MsgSetDateTime, Message) +MESSAGE_CLASS_DEFINITION(SkyMap::MsgReportViewDetails, Message) + +const char* const SkyMap::m_featureIdURI = "sdrangel.feature.skymap"; +const char* const SkyMap::m_featureId = "SkyMap"; + +SkyMap::SkyMap(WebAPIAdapterInterface *webAPIAdapterInterface) : + Feature(m_featureIdURI, webAPIAdapterInterface), + m_multiplier(0.0) +{ + qDebug("SkyMap::SkyMap: webAPIAdapterInterface: %p", webAPIAdapterInterface); + setObjectName(m_featureId); + m_state = StIdle; + m_errorMessage = "SkyMap error"; + m_networkManager = new QNetworkAccessManager(); + QObject::connect( + m_networkManager, + &QNetworkAccessManager::finished, + this, + &SkyMap::networkManagerFinished + ); +} + +SkyMap::~SkyMap() +{ + QObject::disconnect( + m_networkManager, + &QNetworkAccessManager::finished, + this, + &SkyMap::networkManagerFinished + ); + delete m_networkManager; +} + +bool SkyMap::handleMessage(const Message& cmd) +{ + if (MsgConfigureSkyMap::match(cmd)) + { + MsgConfigureSkyMap& cfg = (MsgConfigureSkyMap&) cmd; + qDebug() << "SkyMap::handleMessage: MsgConfigureSkyMap"; + applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce()); + + return true; + } + else if (MsgReportViewDetails::match(cmd)) + { + MsgReportViewDetails& report = (MsgReportViewDetails&) cmd; + m_viewDetails = report.getViewDetails(); + return true; + } + else + { + return false; + } +} + +QByteArray SkyMap::serialize() const +{ + return m_settings.serialize(); +} + +bool SkyMap::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + MsgConfigureSkyMap *msg = MsgConfigureSkyMap::create(m_settings, QList(), true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureSkyMap *msg = MsgConfigureSkyMap::create(m_settings, QList(), true); + m_inputMessageQueue.push(msg); + return false; + } +} + +void SkyMap::applySettings(const SkyMapSettings& settings, const QList& settingsKeys, bool force) +{ + qDebug() << "SkyMap::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force; + + if (settingsKeys.contains("useReverseAPI")) + { + bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) || + settingsKeys.contains("reverseAPIAddress") || + settingsKeys.contains("reverseAPIPort") || + settingsKeys.contains("reverseAPIFeatureSetIndex") || + settingsKeys.contains("m_reverseAPIFeatureIndex"); + webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force); + } + + if (force) { + m_settings = settings; + } else { + m_settings.applySettings(settingsKeys, settings); + } +} + +int SkyMap::webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) run; + (void) errorMessage; + getFeatureStateStr(*response.getState()); + return 202; +} + +int SkyMap::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSkyMapSettings(new SWGSDRangel::SWGSkyMapSettings()); + response.getSkyMapSettings()->init(); + webapiFormatFeatureSettings(response, m_settings); + return 200; +} + +int SkyMap::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + SkyMapSettings settings = m_settings; + webapiUpdateFeatureSettings(settings, featureSettingsKeys, response); + + MsgConfigureSkyMap *msg = MsgConfigureSkyMap::create(settings, featureSettingsKeys, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureSkyMap *msgToGUI = MsgConfigureSkyMap::create(settings, featureSettingsKeys, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatFeatureSettings(response, settings); + + return 200; +} + +int SkyMap::webapiReportGet( + SWGSDRangel::SWGFeatureReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSkyMapReport(new SWGSDRangel::SWGSkyMapReport()); + response.getSkyMapReport()->init(); + webapiFormatFeatureReport(response); + return 200; +} + +int SkyMap::webapiActionsPost( + const QStringList& featureActionsKeys, + SWGSDRangel::SWGFeatureActions& query, + QString& errorMessage) +{ + SWGSDRangel::SWGSkyMapActions *swgSkyMapActions = query.getSkyMapActions(); + + if (swgSkyMapActions) + { + if (featureActionsKeys.contains("find")) + { + QString id = *swgSkyMapActions->getFind(); + + if (getMessageQueueToGUI()) { + getMessageQueueToGUI()->push(MsgFind::create(id)); + } + } + /*if (featureActionsKeys.contains("setDateTime")) + { + QString dateTimeString = *swgSkyMapActions->getSetDateTime(); + QDateTime dateTime = QDateTime::fromString(dateTimeString, Qt::ISODateWithMs); + + if (getMessageQueueToGUI()) { + getMessageQueueToGUI()->push(MsgSetDateTime::create(dateTime)); + } + }*/ + return 202; + } + else + { + errorMessage = "Missing SkyMapActions in query"; + return 400; + } + return 400; +} + +void SkyMap::webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const SkyMapSettings& settings) +{ + response.getSkyMapSettings()->setDisplayNames(settings.m_displayNames ? 1 : 0); + response.getSkyMapSettings()->setDisplayConstellations(settings.m_displayConstellations ? 1 : 0); + response.getSkyMapSettings()->setDisplayReticle(settings.m_displayReticle ? 1 : 0); + response.getSkyMapSettings()->setDisplayGrid(settings.m_displayGrid ? 1 : 0); + response.getSkyMapSettings()->setDisplayAntennaFoV(settings.m_displayAntennaFoV ? 1 : 0); + response.getSkyMapSettings()->setMap(new QString(settings.m_map)); + response.getSkyMapSettings()->setBackground(new QString(settings.m_background)); + response.getSkyMapSettings()->setProjection(new QString(settings.m_projection)); + response.getSkyMapSettings()->setSource(new QString(settings.m_source)); + response.getSkyMapSettings()->setTrack(settings.m_track ? 1 : 0); + response.getSkyMapSettings()->setLatitude(settings.m_latitude); + response.getSkyMapSettings()->setLongitude(settings.m_longitude); + response.getSkyMapSettings()->setAltitude(settings.m_altitude); + response.getSkyMapSettings()->setHpbw(settings.m_hpbw); + response.getSkyMapSettings()->setUseMyPosition(settings.m_useMyPosition); + + if (response.getSkyMapSettings()->getTitle()) { + *response.getSkyMapSettings()->getTitle() = settings.m_title; + } else { + response.getSkyMapSettings()->setTitle(new QString(settings.m_title)); + } + + response.getSkyMapSettings()->setRgbColor(settings.m_rgbColor); + response.getSkyMapSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getSkyMapSettings()->getReverseApiAddress()) { + *response.getSkyMapSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getSkyMapSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getSkyMapSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getSkyMapSettings()->setReverseApiFeatureSetIndex(settings.m_reverseAPIFeatureSetIndex); + response.getSkyMapSettings()->setReverseApiFeatureIndex(settings.m_reverseAPIFeatureIndex); + + if (settings.m_rollupState) + { + if (response.getSkyMapSettings()->getRollupState()) + { + settings.m_rollupState->formatTo(response.getSkyMapSettings()->getRollupState()); + } + else + { + SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState(); + settings.m_rollupState->formatTo(swgRollupState); + response.getSkyMapSettings()->setRollupState(swgRollupState); + } + } +} + +void SkyMap::webapiUpdateFeatureSettings( + SkyMapSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response) +{ + if (featureSettingsKeys.contains("displayNames")) { + settings.m_displayNames = response.getSkyMapSettings()->getDisplayNames(); + } + if (featureSettingsKeys.contains("displayConstellations")) { + settings.m_displayConstellations = response.getSkyMapSettings()->getDisplayConstellations(); + } + if (featureSettingsKeys.contains("displayReticle")) { + settings.m_displayReticle = response.getSkyMapSettings()->getDisplayReticle(); + } + if (featureSettingsKeys.contains("displayGrid")) { + settings.m_displayGrid = response.getSkyMapSettings()->getDisplayGrid(); + } + if (featureSettingsKeys.contains("displayAntennaFoV")) { + settings.m_displayAntennaFoV = response.getSkyMapSettings()->getDisplayAntennaFoV(); + } + if (featureSettingsKeys.contains("map")) { + settings.m_map = *response.getSkyMapSettings()->getMap(); + } + if (featureSettingsKeys.contains("background")) { + settings.m_background = *response.getSkyMapSettings()->getBackground(); + } + if (featureSettingsKeys.contains("projection")) { + settings.m_projection = *response.getSkyMapSettings()->getProjection(); + } + if (featureSettingsKeys.contains("source")) { + settings.m_source = *response.getSkyMapSettings()->getSource(); + } + if (featureSettingsKeys.contains("track")) { + settings.m_track = response.getSkyMapSettings()->getTrack(); + } + if (featureSettingsKeys.contains("latitude")) { + settings.m_latitude = response.getSkyMapSettings()->getLatitude(); + } + if (featureSettingsKeys.contains("longitude")) { + settings.m_longitude = response.getSkyMapSettings()->getLongitude(); + } + if (featureSettingsKeys.contains("altitude")) { + settings.m_altitude = response.getSkyMapSettings()->getAltitude(); + } + if (featureSettingsKeys.contains("hpbw")) { + settings.m_hpbw = response.getSkyMapSettings()->getHpbw(); + } + if (featureSettingsKeys.contains("useMyPosition")) { + settings.m_useMyPosition = response.getSkyMapSettings()->getUseMyPosition(); + } + if (featureSettingsKeys.contains("title")) { + settings.m_title = *response.getSkyMapSettings()->getTitle(); + } + if (featureSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getSkyMapSettings()->getRgbColor(); + } + if (featureSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getSkyMapSettings()->getUseReverseApi() != 0; + } + if (featureSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getSkyMapSettings()->getReverseApiAddress(); + } + if (featureSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getSkyMapSettings()->getReverseApiPort(); + } + if (featureSettingsKeys.contains("reverseAPIFeatureSetIndex")) { + settings.m_reverseAPIFeatureSetIndex = response.getSkyMapSettings()->getReverseApiFeatureSetIndex(); + } + if (featureSettingsKeys.contains("reverseAPIFeatureIndex")) { + settings.m_reverseAPIFeatureIndex = response.getSkyMapSettings()->getReverseApiFeatureIndex(); + } + if (settings.m_rollupState && featureSettingsKeys.contains("rollupState")) { + settings.m_rollupState->updateFrom(featureSettingsKeys, response.getSkyMapSettings()->getRollupState()); + } +} + +void SkyMap::webapiReverseSendSettings(const QList& featureSettingsKeys, const SkyMapSettings& settings, bool force) +{ + SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = new SWGSDRangel::SWGFeatureSettings(); + // swgFeatureSettings->setOriginatorFeatureIndex(getIndexInDeviceSet()); + // swgFeatureSettings->setOriginatorFeatureSetIndex(getDeviceSetIndex()); + swgFeatureSettings->setFeatureType(new QString("SkyMap")); + swgFeatureSettings->setSkyMapSettings(new SWGSDRangel::SWGSkyMapSettings()); + SWGSDRangel::SWGSkyMapSettings *swgSkyMapSettings = swgFeatureSettings->getSkyMapSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (featureSettingsKeys.contains("displayNames") || force) { + swgSkyMapSettings->setDisplayNames(settings.m_displayNames); + } + if (featureSettingsKeys.contains("displayConstellations") || force) { + swgSkyMapSettings->setDisplayConstellations(settings.m_displayConstellations); + } + if (featureSettingsKeys.contains("displayReticle") || force) { + swgSkyMapSettings->setDisplayReticle(settings.m_displayReticle); + } + if (featureSettingsKeys.contains("displayGrid") || force) { + swgSkyMapSettings->setDisplayGrid(settings.m_displayGrid); + } + if (featureSettingsKeys.contains("displayAntennaFoV") || force) { + swgSkyMapSettings->setDisplayAntennaFoV(settings.m_displayAntennaFoV); + } + if (featureSettingsKeys.contains("map") || force) { + swgSkyMapSettings->setMap(new QString(settings.m_map)); + } + if (featureSettingsKeys.contains("background") || force) { + swgSkyMapSettings->setBackground(new QString(settings.m_background)); + } + if (featureSettingsKeys.contains("projection") || force) { + swgSkyMapSettings->setProjection(new QString(settings.m_projection)); + } + if (featureSettingsKeys.contains("source") || force) { + swgSkyMapSettings->setSource(new QString(settings.m_source)); + } + if (featureSettingsKeys.contains("track") || force) { + swgSkyMapSettings->setTrack(settings.m_track); + } + if (featureSettingsKeys.contains("latitude") || force) { + swgSkyMapSettings->setLatitude(settings.m_latitude); + } + if (featureSettingsKeys.contains("longitude") || force) { + swgSkyMapSettings->setLongitude(settings.m_longitude); + } + if (featureSettingsKeys.contains("altitude") || force) { + swgSkyMapSettings->setAltitude(settings.m_altitude); + } + if (featureSettingsKeys.contains("hpbw") || force) { + swgSkyMapSettings->setHpbw(settings.m_hpbw); + } + if (featureSettingsKeys.contains("useMyPosition") || force) { + swgSkyMapSettings->setTrack(settings.m_useMyPosition); + } + if (featureSettingsKeys.contains("title") || force) { + swgSkyMapSettings->setTitle(new QString(settings.m_title)); + } + if (featureSettingsKeys.contains("rgbColor") || force) { + swgSkyMapSettings->setRgbColor(settings.m_rgbColor); + } + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIFeatureSetIndex) + .arg(settings.m_reverseAPIFeatureIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgFeatureSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgFeatureSettings; +} + +void SkyMap::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response) +{ + QString skymapDateTime = getSkyMapDateTime().toString(Qt::ISODateWithMs); + if (response.getSkyMapReport()->getDateTime()) { + //*response.getSkyMapReport()->getDateTime() = skymapDateTime; + *response.getSkyMapReport()->getDateTime() = m_viewDetails.m_dateTime.toString(Qt::ISODateWithMs); + } else { + //response.getSkyMapReport()->setDateTime(new QString(skymapDateTime)); + response.getSkyMapReport()->setDateTime(new QString(m_viewDetails.m_dateTime.toString(Qt::ISODateWithMs))); + } + response.getSkyMapReport()->setRa(m_viewDetails.m_ra); + response.getSkyMapReport()->setDec(m_viewDetails.m_dec); + response.getSkyMapReport()->setAzimuth(m_viewDetails.m_azimuth); + response.getSkyMapReport()->setElevation(m_viewDetails.m_elevation); + response.getSkyMapReport()->setFov(m_viewDetails.m_fov); + response.getSkyMapReport()->setLatitude(m_viewDetails.m_latitude); + response.getSkyMapReport()->setLongitude(m_viewDetails.m_longitude); +} + +void SkyMap::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "SkyMap::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("SkyMap::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} + +void SkyMap::setSkyMapDateTime(QDateTime skymapDateTime, QDateTime systemDateTime, double multiplier) +{ + QMutexLocker mutexLocker(&m_dateTimeMutex); + m_skymapDateTime = skymapDateTime; + m_systemDateTime = systemDateTime; + m_multiplier = multiplier; +} + +QDateTime SkyMap::getSkyMapDateTime() +{ + QMutexLocker mutexLocker(&m_dateTimeMutex); + if (m_multiplier == 0.0) + { + return m_skymapDateTime; + } + else + { + // It's not possible to synchronously get the time from Cesium + // so we calculate it based on the system clock difference from + // when changes were made to the clock GUI elements + // Should be accurate enough for satellite tracker + qint64 diffMsecs = m_systemDateTime.msecsTo(QDateTime::currentDateTime()); + return m_skymapDateTime.addMSecs(diffMsecs * m_multiplier); + } +} diff --git a/plugins/feature/skymap/skymap.h b/plugins/feature/skymap/skymap.h new file mode 100644 index 000000000..cc9d794fb --- /dev/null +++ b/plugins/feature/skymap/skymap.h @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB // +// Copyright (C) 2020 Kacper Michajłow // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // +// Copyright (C) 2022 Jiří Pinkava // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_SKYMAP_H_ +#define INCLUDE_FEATURE_SKYMAP_H_ + +#include +#include +#include +#include + +#include "feature/feature.h" +#include "util/message.h" + +#include "skymapsettings.h" + +class WebAPIAdapterInterface; +class QNetworkAccessManager; +class QNetworkReply; + +namespace SWGSDRangel { + class SWGDeviceState; +} + +class SkyMap : public Feature +{ + Q_OBJECT +public: + + class MsgConfigureSkyMap : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const SkyMapSettings& getSettings() const { return m_settings; } + const QList& getSettingsKeys() const { return m_settingsKeys; } + bool getForce() const { return m_force; } + + static MsgConfigureSkyMap* create(const SkyMapSettings& settings, const QList& settingsKeys, bool force) { + return new MsgConfigureSkyMap(settings, settingsKeys, force); + } + + private: + SkyMapSettings m_settings; + QList m_settingsKeys; + bool m_force; + + MsgConfigureSkyMap(const SkyMapSettings& settings, const QList& settingsKeys, bool force) : + Message(), + m_settings(settings), + m_settingsKeys(settingsKeys), + m_force(force) + { } + }; + + class MsgFind : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QString getTarget() const { return m_target; } + + static MsgFind* create(const QString& target) { + return new MsgFind(target); + } + + private: + QString m_target; + + MsgFind(const QString& target) : + Message(), + m_target(target) + {} + }; + + class MsgSetDateTime : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QDateTime getDateTime() const { return m_dateTime; } + + static MsgSetDateTime* create(const QDateTime& dateTime) { + return new MsgSetDateTime(dateTime); + } + + private: + QDateTime m_dateTime; + + MsgSetDateTime(const QDateTime& dateTime) : + Message(), + m_dateTime(dateTime) + {} + }; + + struct ViewDetails { + double m_ra; + double m_dec; + float m_azimuth; + float m_elevation; + float m_fov; + float m_latitude; + float m_longitude; + QDateTime m_dateTime; + + ViewDetails() : + m_ra(0.0), + m_dec(0.0), + m_azimuth(0.0f), + m_elevation(0.0f), + m_fov(0.0f), + m_latitude(0.0f), + m_longitude(0.0f) + { + } + }; + + class MsgReportViewDetails : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const ViewDetails& getViewDetails() { return m_viewDetails; } + + static MsgReportViewDetails* create(const ViewDetails& viewDetails) { + return new MsgReportViewDetails(viewDetails); + } + + private: + ViewDetails m_viewDetails; + + MsgReportViewDetails(const ViewDetails& viewDetails) : + Message(), + m_viewDetails(viewDetails) + {} + }; + + SkyMap(WebAPIAdapterInterface *webAPIAdapterInterface); + virtual ~SkyMap(); + virtual void destroy() { delete this; } + virtual bool handleMessage(const Message& cmd); + + virtual void getIdentifier(QString& id) const { id = objectName(); } + virtual QString getIdentifier() const { return objectName(); } + virtual void getTitle(QString& title) const { title = m_settings.m_title; } + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int webapiRun(bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGFeatureReport& response, + QString& errorMessage); + + virtual int webapiActionsPost( + const QStringList& featureActionsKeys, + SWGSDRangel::SWGFeatureActions& query, + QString& errorMessage); + + static void webapiFormatFeatureSettings( + SWGSDRangel::SWGFeatureSettings& response, + const SkyMapSettings& settings); + + static void webapiUpdateFeatureSettings( + SkyMapSettings& settings, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response); + + void setSkyMapDateTime(QDateTime skymapDateTime, QDateTime systemDateTime, double multiplier); + QDateTime getSkyMapDateTime(); + + static const char* const m_featureIdURI; + static const char* const m_featureId; + +private: + SkyMapSettings m_settings; + ViewDetails m_viewDetails; + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + void applySettings(const SkyMapSettings& settings, const QList& settingsKeys, bool force = false); + void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); + void webapiReverseSendSettings(const QList& featureSettingsKeys, const SkyMapSettings& settings, bool force); + + QDateTime m_skymapDateTime; + QDateTime m_systemDateTime; + double m_multiplier; + QRecursiveMutex m_dateTimeMutex; + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // INCLUDE_FEATURE_SKYMAP_H_ diff --git a/plugins/feature/skymap/skymap.qrc b/plugins/feature/skymap/skymap.qrc new file mode 100644 index 000000000..a68c6bb2e --- /dev/null +++ b/plugins/feature/skymap/skymap.qrc @@ -0,0 +1,7 @@ + + + html/wwt.html + html/esasky.html + html/aladin.html + + diff --git a/plugins/feature/skymap/skymapgui.cpp b/plugins/feature/skymap/skymapgui.cpp new file mode 100644 index 000000000..1cc7e9655 --- /dev/null +++ b/plugins/feature/skymap/skymapgui.cpp @@ -0,0 +1,1074 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // +// Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +#include +#include +#include + +#include "feature/featureuiset.h" +#include "gui/basicfeaturesettingsdialog.h" +#include "gui/dialogpositioner.h" +#include "util/astronomy.h" +#include "util/units.h" +#include "maincore.h" + +#include "ui_skymapgui.h" +#include "skymap.h" +#include "skymapgui.h" +#include "skymapsettingsdialog.h" + +#include "SWGTargetAzimuthElevation.h" +#include "SWGSkyMapTarget.h" + +SkyMapGUI* SkyMapGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature) +{ + SkyMapGUI* gui = new SkyMapGUI(pluginAPI, featureUISet, feature); + return gui; +} + +void SkyMapGUI::destroy() +{ + delete this; +} + +void SkyMapGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applyAllSettings(); +} + +QByteArray SkyMapGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool SkyMapGUI::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + m_feature->setWorkspaceIndex(m_settings.m_workspaceIndex); + displaySettings(); + applyAllSettings(); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +bool SkyMapGUI::handleMessage(const Message& message) +{ + if (SkyMap::MsgConfigureSkyMap::match(message)) + { + qDebug("SkyMapGUI::handleMessage: SkyMap::MsgConfigureSkyMap"); + const SkyMap::MsgConfigureSkyMap& cfg = (SkyMap::MsgConfigureSkyMap&) message; + + if (cfg.getForce()) { + m_settings = cfg.getSettings(); + } else { + m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings()); + } + + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + + return true; + } + else if (SkyMap::MsgFind::match(message)) + { + SkyMap::MsgFind& msgFind = (SkyMap::MsgFind&) message; + find(msgFind.getTarget()); + return true; + } + else if (SkyMap::MsgSetDateTime::match(message)) + { + SkyMap::MsgSetDateTime& msgSetDateTime = (SkyMap::MsgSetDateTime&) message; + setDateTime(msgSetDateTime.getDateTime()); + return true; + } + else if (MainCore::MsgTargetAzimuthElevation::match(message)) + { + MainCore::MsgTargetAzimuthElevation& msg = (MainCore::MsgTargetAzimuthElevation&) message; + + // Ignore messages from StarTracker, as we use MsgSkyMapTarget instead, as more accurate and no refraction correction + if ((msg.getPipeSource() == m_source) && !m_settings.m_source.contains("StarTracker")) + { + // Convert from Az/Alt to RA/Dec + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = msg.getSWGTargetAzimuthElevation(); + AzAlt aa; + aa.az = swgTarget->getAzimuth(); + aa.alt = swgTarget->getElevation(); + + QGeoCoordinate position = getPosition(); + RADec rd; + QDateTime dateTime = QDateTime::currentDateTime(); + + rd = Astronomy::azAltToRaDec(aa, position.latitude(), position.longitude(), dateTime); + + // Convert from JNOW to J2000 + double jd = Astronomy::julianDate(dateTime); + rd = Astronomy::precess(rd, jd, Astronomy::jd_j2000()); + + m_ra = rd.ra; + m_dec = rd.dec; + if (m_settings.m_track) { + m_webInterface->setView(rd.ra, rd.dec); + } + + m_webInterface->setAntennaFoV(m_settings.m_hpbw); + } + return true; + } + else if (MainCore::MsgSkyMapTarget::match(message)) + { + MainCore::MsgSkyMapTarget& msg = (MainCore::MsgSkyMapTarget&) message; + if (msg.getPipeSource() == m_source) + { + SWGSDRangel::SWGSkyMapTarget *swgTarget = msg.getSWGSkyMapTarget(); + m_ra = swgTarget->getRa(); + m_dec = swgTarget->getDec(); + if (m_settings.m_track) { + m_webInterface->setView(m_ra, m_dec); + } + setPosition(swgTarget->getLatitude(), swgTarget->getLongitude(), swgTarget->getAltitude()); + QDateTime dateTime = QDateTime::currentDateTime(); + if (swgTarget->getDateTime()) + { + QString dateTimeString = *swgTarget->getDateTime(); + if (!dateTimeString.isEmpty()) { + dateTime = QDateTime::fromString(*swgTarget->getDateTime(), Qt::ISODateWithMs); + } + } + setDateTime(dateTime); + + m_webInterface->setAntennaFoV(swgTarget->getHpbw()); + } + return true; + } + + return false; +} + +void SkyMapGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop())) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +void SkyMapGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + (void) widget; + (void) rollDown; + + getRollupContents()->saveState(m_rollupState); + applySetting("rollupState"); +} + +SkyMapGUI::SkyMapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) : + FeatureGUI(parent), + ui(new Ui::SkyMapGUI), + m_pluginAPI(pluginAPI), + m_featureUISet(featureUISet), + m_doApplySettings(true), + m_source(nullptr), + m_availableChannelOrFeatureHandler(SkyMapSettings::m_pipeURIs, {"target", "skymap.target"}) +{ + m_feature = feature; + setAttribute(Qt::WA_DeleteOnClose, true); + m_helpURL = "plugins/feature/skymap/readme.md"; + RollupContents *rollupContents = getRollupContents(); + ui->setupUi(rollupContents); + setSizePolicy(rollupContents->sizePolicy()); + rollupContents->arrangeRollups(); + connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + + m_webInterface = new WebInterface(); + connect(m_webInterface, &WebInterface::received, this, &SkyMapGUI::receivedEvent); + + // Web server to serve dynamic files from QResources + m_webPort = 0; + m_webServer = new WebServer(m_webPort); + + m_webServer->addSubstitution("/skymap/html/wwt.html", "$WS_PORT$", QString::number(m_webInterface->serverPort())); + m_webServer->addSubstitution("/skymap/html/esasky.html", "$WS_PORT$", QString::number(m_webInterface->serverPort())); + m_webServer->addSubstitution("/skymap/html/aladin.html", "$WS_PORT$", QString::number(m_webInterface->serverPort())); + + ui->tabs->tabBar()->tabButton(0, QTabBar::RightSide)->resize(0, 0); // Hide close button + ui->web->setTabs(ui->tabs); + ui->web->load(QUrl(QString("http://127.0.0.1:%1/skymap/html/wwt.html").arg(m_webPort))); + ui->web->show(); + + m_skymap = reinterpret_cast(feature); + m_skymap->setMessageQueueToGUI(&m_inputMessageQueue); + + m_settings.setRollupState(&m_rollupState); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + + QWebEngineSettings *settings = ui->web->settings(); + settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); + connect(ui->web->page(), &QWebEnginePage::fullScreenRequested, this, &SkyMapGUI::fullScreenRequested); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + connect(ui->web->page(), &QWebEnginePage::loadingChanged, this, &SkyMapGUI::loadingChanged); + connect(ui->web, &QWebEngineView::renderProcessTerminated, this, &SkyMapGUI::renderProcessTerminated); +#endif + + // Default to My Position + m_settings.m_latitude = MainCore::instance()->getSettings().getLatitude(); + m_settings.m_longitude = MainCore::instance()->getSettings().getLongitude(); + m_settings.m_altitude = MainCore::instance()->getSettings().getAltitude(); + + // Get updated when position changes + connect(&MainCore::instance()->getSettings(), &MainSettings::preferenceChanged, this, &SkyMapGUI::preferenceChanged); + + displaySettings(); + applyAllSettings(); + + makeUIConnections(); + m_resizer.enableChildMouseTracking(); + + QObject::connect(&m_availableChannelOrFeatureHandler, &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, &SkyMapGUI::updateSourceList); + QObject::connect(&m_availableChannelOrFeatureHandler, &AvailableChannelOrFeatureHandler::messageEnqueued, this, &SkyMapGUI::handlePipeMessageQueue); + m_availableChannelOrFeatureHandler.scanAvailableChannelsAndFeatures(); + + connect(&m_wtml, &WTML::dataUpdated, this, &SkyMapGUI::wtmlUpdated); + m_wtml.getData(); +} + +SkyMapGUI::~SkyMapGUI() +{ + QObject::disconnect(&m_availableChannelOrFeatureHandler, &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, &SkyMapGUI::updateSourceList); + if (m_webServer) + { + m_webServer->close(); + delete m_webServer; + } + delete ui; +} + +void SkyMapGUI::setWorkspaceIndex(int index) +{ + m_settings.m_workspaceIndex = index; + m_feature->setWorkspaceIndex(index); +} + +void SkyMapGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void SkyMapGUI::on_map_currentIndexChanged(int index) +{ + (void) index; + + m_settings.m_map = ui->map->currentText(); + applySetting("map"); + + if (m_settings.m_map == "WWT") { + ui->web->load(QUrl(QString("http://127.0.0.1:%1/skymap/html/wwt.html").arg(m_webPort))); + } else if (m_settings.m_map == "ESASky") { + ui->web->load(QUrl(QString("http://127.0.0.1:%1/skymap/html/esasky.html").arg(m_webPort))); + } else if (m_settings.m_map == "Aladin") { + ui->web->load(QUrl(QString("http://127.0.0.1:%1/skymap/html/aladin.html").arg(m_webPort))); + } + updateToolbar(); + updateBackgrounds(); +} + +void SkyMapGUI::on_background_currentIndexChanged(int index) +{ + if (index >= 0) + { + m_settings.m_background = ui->background->currentText(); + applySetting("background"); + m_webInterface->setBackground(backgroundID(m_settings.m_background)); + } +} + +void SkyMapGUI::on_projection_currentIndexChanged(int index) +{ + if (index >= 0) + { + m_settings.m_projection = ui->projection->currentText(); + applySetting("projection"); + if (m_settings.m_map == "WWT") { + updateBackgrounds(); + } + m_webInterface->setProjection(m_settings.m_projection); + if (m_settings.m_map == "WWT") { + m_webInterface->setBackground(backgroundID(m_settings.m_background)); + } + } +} + +void SkyMapGUI::on_source_currentIndexChanged(int index) +{ + if (index >= 0) + { + m_settings.m_source = ui->source->currentText(); + applySetting("source"); + ui->track->setEnabled(true); + } + else + { + ui->track->setChecked(false); + ui->track->setEnabled(false); + } +} + +void SkyMapGUI::renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode) +{ + qDebug() << "SkyMapGUI::renderProcessTerminated: " << terminationStatus << "exitCode" << exitCode; +} + +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + +void SkyMapGUI::loadingChanged(const QWebEngineLoadingInfo &loadingInfo) +{ + if (loadingInfo.status() == QWebEngineLoadingInfo::LoadFailedStatus) + { + qDebug() << "SkyMapGUI::loadingChanged: Failed to load " << loadingInfo.url().toString() + << "errorString: " << loadingInfo.errorString() << " " + << "errorDomain:" << loadingInfo.errorDomain() + << "errorCode:" << loadingInfo.errorCode() + ; + } +} +#endif + +void SkyMapGUI::initSkyMap() +{ + QGeoCoordinate position = getPosition(); + updateToolbar(); + m_webInterface->setWWTSettings(m_settings.m_wwtSettings); + m_webInterface->setPosition(position); + m_webInterface->showNames(m_settings.m_displayNames); + m_webInterface->showConstellations(m_settings.m_displayConstellations); + m_webInterface->showReticle(m_settings.m_displayReticle); + m_webInterface->showGrid(m_settings.m_displayGrid); + m_webInterface->showAntennaFoV(m_settings.m_displayAntennaFoV); + m_webInterface->setProjection(m_settings.m_projection); + m_webInterface->setBackground(backgroundID(m_settings.m_background)); +} + +void SkyMapGUI::displaySettings() +{ + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_settings.m_title); + setTitle(m_settings.m_title); + blockApplySettings(true); + ui->displayNames->setChecked(m_settings.m_displayNames); + int idx = ui->map->findText(m_settings.m_map); + if (idx >= 0) { + ui->map->setCurrentIndex(idx); + } + ui->displayConstellations->setChecked(m_settings.m_displayConstellations); + ui->displayReticle->setChecked(m_settings.m_displayReticle); + ui->displayGrid->setChecked(m_settings.m_displayGrid); + ui->displayAntennaFoV->setChecked(m_settings.m_displayAntennaFoV); + idx = ui->background->findText(m_settings.m_background); + if (idx >= 0) { + ui->background->setCurrentIndex(idx); + } + ui->track->setChecked(m_settings.m_track); + idx = ui->source->findText(m_settings.m_source); + if (idx >= 0) + { + ui->source->setCurrentIndex(idx); + ui->track->setEnabled(true); + } + else + { + ui->track->setChecked(false); + ui->track->setEnabled(false); + } + initSkyMap(); + getRollupContents()->restoreState(m_rollupState); + blockApplySettings(false); +} + +void SkyMapGUI::onMenuDialogCalled(const QPoint &p) +{ + if (m_contextMenuType == ContextMenuChannelSettings) + { + BasicFeatureSettingsDialog dialog(this); + dialog.setTitle(m_settings.m_title); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIFeatureSetIndex(m_settings.m_reverseAPIFeatureSetIndex); + dialog.setReverseAPIFeatureIndex(m_settings.m_reverseAPIFeatureIndex); + dialog.setDefaultTitle(m_displayedName); + + dialog.move(p); + new DialogPositioner(&dialog, false); + dialog.exec(); + + m_settings.m_title = dialog.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIFeatureSetIndex = dialog.getReverseAPIFeatureSetIndex(); + m_settings.m_reverseAPIFeatureIndex = dialog.getReverseAPIFeatureIndex(); + + setTitle(m_settings.m_title); + setTitleColor(m_settings.m_rgbColor); + + QList settingsKeys({ + "rgbColor", + "title", + "useReverseAPI", + "reverseAPIAddress", + "reverseAPIPort", + "reverseAPIDeviceIndex", + "reverseAPIChannelIndex" + }); + + applySettings(settingsKeys); + } + + resetContextMenuType(); +} + +void SkyMapGUI::applySetting(const QString& settingsKey) +{ + applySettings({settingsKey}); +} + +void SkyMapGUI::applySettings(const QStringList& settingsKeys, bool force) +{ + m_settingsKeys.append(settingsKeys); + if (m_doApplySettings) + { + SkyMap::MsgConfigureSkyMap* message = SkyMap::MsgConfigureSkyMap::create(m_settings, m_settingsKeys, force); + m_skymap->getInputMessageQueue()->push(message); + m_settingsKeys.clear(); + + m_availableChannelOrFeatureHandler.deregisterPipes(m_source, {"target", "skymap.target"}); + + QObject *oldSource = m_source; + m_source = m_availableChannelOrFeatureHandler.registerPipes(m_settings.m_source, {"target", "skymap.target"}); + + // When we change plugins, default to current date and time and My Position, until we get something different + if (oldSource && !m_source) + { + setDateTime(QDateTime::currentDateTime()); + setPosition(MainCore::instance()->getSettings().getLatitude(), + MainCore::instance()->getSettings().getLongitude(), + MainCore::instance()->getSettings().getAltitude()); + } + } +} + +void SkyMapGUI::applyAllSettings() +{ + applySettings(QStringList(), true); +} + +void SkyMapGUI::find(const QString& text) +{ + float ra, dec; + + // WWT's find doesn't support coordinates, so we check here + if (Units::stringToRADec(text, ra, dec)) { + m_webInterface->setView(ra, dec); + } else { + m_webInterface->track(text); + } +} + +void SkyMapGUI::on_find_returnPressed() +{ + find(ui->find->text().trimmed()); +} + +void SkyMapGUI::on_displaySettings_clicked() +{ + SkyMapSettingsDialog dialog(&m_settings); + new DialogPositioner(&dialog, true); + if (dialog.exec() == QDialog::Accepted) + { + applySettings(dialog.m_settingsKeysChanged); + + if (dialog.m_settingsKeysChanged.contains("latitude") + || dialog.m_settingsKeysChanged.contains("longitude") + || dialog.m_settingsKeysChanged.contains("altitude") + || dialog.m_settingsKeysChanged.contains("useMyPosition")) { + m_webInterface->setPosition(getPosition()); + } + if (dialog.m_settingsKeysChanged.contains("hpbw")) { + m_webInterface->setAntennaFoV(m_settings.m_hpbw); + } + if (dialog.m_settingsKeysChanged.contains("wwtSettings")) { + m_webInterface->setWWTSettings(m_settings.m_wwtSettings); + } + } +} + +void SkyMapGUI::on_displayNames_clicked(bool checked) +{ + m_settings.m_displayNames = checked; + m_webInterface->showNames(checked); + applySetting("displayNames"); +} + +void SkyMapGUI::on_displayConstellations_clicked(bool checked) +{ + m_settings.m_displayConstellations = checked; + m_webInterface->showConstellations(checked); + applySetting("displayConstellations"); +} + +void SkyMapGUI::on_displayReticle_clicked(bool checked) +{ + m_settings.m_displayReticle = checked; + m_webInterface->showReticle(checked); + applySetting("displayReticle"); +} + +void SkyMapGUI::on_displayGrid_clicked(bool checked) +{ + m_settings.m_displayGrid = checked; + m_webInterface->showGrid(checked); + applySetting("displayGrid"); +} + +void SkyMapGUI::on_displayAntennaFoV_clicked(bool checked) +{ + m_settings.m_displayAntennaFoV = checked; + m_webInterface->showAntennaFoV(checked); + applySetting("displayAntennaFoV"); +} + +void SkyMapGUI::on_track_clicked(bool checked) +{ + m_settings.m_track = checked; + applySetting("track"); + if (m_settings.m_track) { + m_webInterface->setView(m_ra, m_dec); + } +} + +void SkyMapGUI::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) +{ + fullScreenRequest.accept(); + if (fullScreenRequest.toggleOn()) + { + ui->web->setParent(nullptr); + ui->web->showFullScreen(); + } + else + { + ui->tab0->layout()->addWidget(ui->web); + } +} + +void SkyMapGUI::setDateTime(QDateTime dateTime) +{ + m_dateTime = dateTime; + m_webInterface->setDateTime(m_dateTime); +} + +QDateTime SkyMapGUI::getDateTime() const +{ + if (!m_source || !m_dateTime.isValid()) { + return QDateTime::currentDateTime(); + } else { + return m_dateTime; + } +} + +void SkyMapGUI::setPosition(float latitude, float longitude, float altitude) +{ + m_settings.m_latitude = latitude; + m_settings.m_longitude = longitude; + m_settings.m_altitude = altitude; + m_webInterface->setPosition(getPosition()); +} + +QGeoCoordinate SkyMapGUI::getPosition() const +{ + float latitude, longitude, altitude; + + if (m_settings.m_useMyPosition) + { + latitude = MainCore::instance()->getSettings().getLatitude(); + longitude = MainCore::instance()->getSettings().getLongitude(); + altitude = MainCore::instance()->getSettings().getAltitude(); + } + else + { + latitude = m_settings.m_latitude; + longitude = m_settings.m_longitude; + altitude = m_settings.m_altitude; + } + + QGeoCoordinate position(latitude, longitude, altitude); + return position; +} + +void SkyMapGUI::preferenceChanged(int elementType) +{ + Preferences::ElementType pref = (Preferences::ElementType)elementType; + if ((pref == Preferences::Latitude) || (pref == Preferences::Longitude) || (pref == Preferences::Altitude)) + { + QGeoCoordinate position = getPosition(); + m_webInterface->setPosition(position); + } +} + +void SkyMapGUI::makeUIConnections() +{ + QObject::connect(ui->find, &QLineEdit::returnPressed, this, &SkyMapGUI::on_find_returnPressed); + QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &SkyMapGUI::on_displaySettings_clicked); + QObject::connect(ui->displayNames, &QToolButton::clicked, this, &SkyMapGUI::on_displayNames_clicked); + QObject::connect(ui->displayConstellations, &QToolButton::clicked, this, &SkyMapGUI::on_displayConstellations_clicked); + QObject::connect(ui->displayReticle, &QToolButton::clicked, this, &SkyMapGUI::on_displayReticle_clicked); + QObject::connect(ui->displayGrid, &QToolButton::clicked, this, &SkyMapGUI::on_displayGrid_clicked); + QObject::connect(ui->displayAntennaFoV, &QToolButton::clicked, this, &SkyMapGUI::on_displayAntennaFoV_clicked); + QObject::connect(ui->background, qOverload(&QComboBox::currentIndexChanged), this, &SkyMapGUI::on_background_currentIndexChanged); + QObject::connect(ui->map, qOverload(&QComboBox::currentIndexChanged), this, &SkyMapGUI::on_map_currentIndexChanged); + QObject::connect(ui->projection, qOverload(&QComboBox::currentIndexChanged), this, &SkyMapGUI::on_projection_currentIndexChanged); + QObject::connect(ui->source, qOverload(&QComboBox::currentIndexChanged), this, &SkyMapGUI::on_source_currentIndexChanged); + QObject::connect(ui->track, &QToolButton::clicked, this, &SkyMapGUI::on_track_clicked); + QObject::connect(ui->tabs, &QTabWidget::tabCloseRequested, this, &SkyMapGUI::on_tabs_tabCloseRequested); +} + +void SkyMapGUI::receivedEvent(const QJsonObject &obj) +{ + if (obj.contains("event")) + { + QString event = obj.value("event").toString(); + if (event == "view") + { + QStringList status; + + double ra = 0.0, dec = 0.0; + double latitude = 0.0, longitude = 0.0; + double fov = 0.0; + AzAlt aa = {0.0, 0.0}; + QDateTime dateTime; + + if (obj.contains("dateTime")) + { + dateTime = QDateTime::fromString(obj.value("dateTime").toString(), Qt::ISODateWithMs).toLocalTime(); + } + else + { + dateTime = getDateTime(); + } + + if (obj.contains("ra") && obj.contains("dec")) + { + ra = obj.value("ra").toDouble(); + dec = obj.value("dec").toDouble(); + + // Convert from decimal to DMS + QString raDMS = Units::decimalHoursToHoursMinutesAndSeconds(ra); + QString decDMS = Units::decimalDegreesToDegreeMinutesAndSeconds(dec); + + status.append(QString("J2000 RA: %1 Dec: %2") + .arg(raDMS).arg(decDMS)); + } + + if (obj.contains("fov")) + { + fov = obj.value("fov").toDouble(); + + status.append(QString("FoV: %1%2").arg(fov, 0, 'f', 2).arg(QChar(0xb0))); + } + + if (obj.contains("latitude") && obj.contains("longitude")) + { + latitude = obj.value("latitude").toDouble(); + longitude = obj.value("longitude").toDouble(); + + status.append(QString("Lat: %1%3 Long: %2%3") + .arg(latitude).arg(longitude) + .arg(QChar(0xb0))); + } + + if (obj.contains("dateTime")) + { + status.append(QString("Date: %1").arg(dateTime.date().toString())); + status.append(QString("Time: %1").arg(dateTime.time().toString())); + } + + if (obj.contains("ra") && obj.contains("dec") && obj.contains("latitude") && obj.contains("longitude") && obj.contains("dateTime")) + { + // Convert from RA/Dec to Az/Alt + RADec rd = {ra, dec}; + aa = Astronomy::raDecToAzAlt(rd, latitude, longitude, dateTime); + QString az = QString::number(aa.az, 'f', 3); + QString alt = QString::number(aa.alt, 'f', 3); + + status.insert(1, QString("Az: %1%3 Alt: %2%3") + .arg(az).arg(alt) + .arg(QChar(0xb0))); + + sendToRotator(status[0], aa.az, aa.alt); + } + else if (obj.contains("ra") && obj.contains("dec")) + { + RADec rd = {ra, dec}; + QGeoCoordinate position = getPosition(); + + AzAlt aa = Astronomy::raDecToAzAlt(rd, position.latitude(), position.longitude(), dateTime); + sendToRotator(status[0], aa.az, aa.alt); + } + + setStatusText(status.join(" - ")); + + // Send details to SkyMap for use in Web report + SkyMap::ViewDetails viewDetails; + viewDetails.m_ra = ra; + viewDetails.m_dec = dec; + viewDetails.m_azimuth = aa.az; + viewDetails.m_elevation = aa.alt; + viewDetails.m_latitude = latitude; + viewDetails.m_longitude = longitude; + viewDetails.m_fov = fov; + viewDetails.m_dateTime = dateTime; + SkyMap::MsgReportViewDetails* message = SkyMap::MsgReportViewDetails::create(viewDetails); + m_skymap->getInputMessageQueue()->push(message); + + } + else if (event == "ready") + { + initSkyMap(); + } + } + else + { + qDebug() << "SkyMapGUI::receivedEvent - Unexpected event: " << obj; + } +} + +static const QStringList wwtPlanets = { + QStringLiteral("Sun"), + QStringLiteral("Mercury"), + QStringLiteral("Venus"), + QStringLiteral("Earth"), + QStringLiteral("Moon"), + QStringLiteral("Mars"), + QStringLiteral("Jupiter"), + QStringLiteral("Saturn"), + QStringLiteral("Uranus"), + QStringLiteral("Neptune"), + QStringLiteral("Pluto"), + QStringLiteral("Io"), + QStringLiteral("Europa"), + QStringLiteral("Ganymede"), + QStringLiteral("Callisto") +}; + +static const QStringList wwtPlanetIDs = { + QStringLiteral("Sun"), + QStringLiteral("Mercury"), + QStringLiteral("Venus"), + QStringLiteral("Bing Maps Aerial"), //"Earth", + QStringLiteral("Moon"), + QStringLiteral("Visible Imagery"), // Mars + QStringLiteral("Jupiter"), + QStringLiteral("Saturn"), + QStringLiteral("Uranus"), + QStringLiteral("Neptune"), + QStringLiteral("Pluto (New Horizons)"), + QStringLiteral("Io"), + QStringLiteral("Europa"), + QStringLiteral("Ganymede"), + QStringLiteral("Callisto") +}; + +// From https://github.com/cds-astro/aladin-lite/blob/master/src/js/ImageLayer.js +static const QStringList aladinBackgrounds = { + QStringLiteral("DSS colored"), + QStringLiteral("DSS2 Red (F+R)"), + QStringLiteral("2MASS colored"), + QStringLiteral("Density map for Gaia EDR3 (I/350/gaiaedr3)"), + QStringLiteral("PanSTARRS DR1 g"), + QStringLiteral("PanSTARRS DR1 color"), + QStringLiteral("DECaPS DR1 color"), + QStringLiteral("Fermi color"), + QStringLiteral("Halpha"), + QStringLiteral("GALEXGR6_7 NUV"), + QStringLiteral("IRIS colored"), + QStringLiteral("Mellinger colored"), + QStringLiteral("SDSS9 colored"), + QStringLiteral("SDSS9 band-g"), + QStringLiteral("IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)"), + QStringLiteral("VTSS-Ha"), + QStringLiteral("XMM PN colored"), + QStringLiteral("AllWISE color"), + QStringLiteral("GLIMPSE360") +}; + +static const QStringList aladinBackgroundIDs = { + QStringLiteral("P/DSS2/color"), + QStringLiteral("P/DSS2/red"), + QStringLiteral("P/2MASS/color"), + QStringLiteral("P/DM/I/350/gaiaedr3"), + QStringLiteral("P/PanSTARRS/DR1/g"), + QStringLiteral("P/PanSTARRS/DR1/color-z-zg-g"), + QStringLiteral("P/DECaPS/DR1/color"), + QStringLiteral("P/Fermi/color"), + QStringLiteral("P/Finkbeiner"), + QStringLiteral("P/GALEXGR6_7/NUV"), + QStringLiteral("P/IRIS/color"), + QStringLiteral("P/Mellinger/color"), + QStringLiteral("P/SDSS9/color"), + QStringLiteral("P/SDSS9/g"), + QStringLiteral("P/SPITZER/color"), + QStringLiteral("P/VTSS/Ha"), + QStringLiteral("xcatdb/P/XMM/PN/color"), + QStringLiteral("P/allWISE/color"), + QStringLiteral("P/GLIMPSE360") +}; + +QString SkyMapGUI::backgroundID(const QString& name) +{ + QString id = name; + + if (m_settings.m_map == "Aladin") + { + int idx = aladinBackgrounds.indexOf(name); + if (idx >= 0) { + id = aladinBackgroundIDs[idx]; + } + } + else if (m_settings.m_map == "WWT") + { + if (m_settings.m_projection == "Solar system") + { + m_webInterface->track(m_settings.m_background); + id = "Solar system"; + } + else + { + int idx = wwtPlanets.indexOf(name); + if (idx >= 0) { + id = wwtPlanetIDs[idx]; + } + } + } + return id; +} + +void SkyMapGUI::updateBackgrounds() +{ + QStringList backgrounds; + + if (m_settings.m_map == "WWT") { + if (m_settings.m_projection == "Sky") { + backgrounds = m_wwtBackgrounds; + } else if (m_settings.m_projection == "Solar system") { + backgrounds = wwtPlanets; + } else { + backgrounds = wwtPlanets; + } + } else if (m_settings.m_map == "ESASky") { + backgrounds = QStringList(); + } else if (m_settings.m_map == "Aladin") { + backgrounds = aladinBackgrounds; + } + + ui->background->blockSignals(true); + ui->background->clear(); + for (int i = 0; i < backgrounds.size(); i++) { + ui->background->addItem(backgrounds[i]); + } + ui->background->blockSignals(false); + int idx = ui->background->findText(m_settings.m_background); + if (idx >= 0) { + ui->background->setCurrentIndex(idx); + } else { + ui->background->setCurrentIndex(0); + } + + on_background_currentIndexChanged(ui->projection->currentIndex()); +} + +void SkyMapGUI::wtmlUpdated(const QList& dataSets) +{ + m_wwtBackgrounds.clear(); + for (int i = 0; i < dataSets.size(); i++) + { + if (dataSets[i].m_dataSetType == "Sky") { + m_wwtBackgrounds.append(dataSets[i].m_name); + } + } + updateBackgrounds(); +} + +void SkyMapGUI::updateProjection() +{ + QStringList projections; + + if (m_settings.m_map == "WWT") { + projections = QStringList{"Sky", "Solar system", "Planet"}; + } else if (m_settings.m_map == "ESASky") { + projections = QStringList(); + } else if (m_settings.m_map == "Aladin") { + projections = QStringList{"SIN", "TAN", "STG", "ZEA", "FEYE", "AIR", "ARC", "NCP", "MER", "CAR", "CEA", "CYP", "AIT", "MOL", "PAR", "SFL", "COD", "HPX"}; + } + + ui->projection->blockSignals(true); + ui->projection->clear(); + for (int i = 0; i < projections.size(); i++){ + ui->projection->addItem(projections[i]); + } + ui->projection->blockSignals(false); + int idx = ui->projection->findText(m_settings.m_projection); + if (idx >= 0) { + ui->projection->setCurrentIndex(idx); + } else { + ui->projection->setCurrentIndex(0); + } + + on_projection_currentIndexChanged(ui->projection->currentIndex()); +} + +void SkyMapGUI::updateToolbar() +{ + bool constellationsVisible = false; + bool reticleVisible = true; + bool namesVisible = false; + bool projectionVisible = true; + bool backgroundVisible = true; + + if (m_settings.m_map == "WWT") + { + constellationsVisible = true; + namesVisible = true; + } + else if (m_settings.m_map == "ESASky") + { + projectionVisible = false; + backgroundVisible = false; + reticleVisible = false; + } + + ui->background->setVisible(backgroundVisible); + ui->projection->setVisible(projectionVisible); + + ui->displayNames->setVisible(namesVisible); + ui->displayConstellations->setVisible(constellationsVisible); + ui->displayReticle->setVisible(reticleVisible); + + updateProjection(); +} + +void SkyMapGUI::on_tabs_tabCloseRequested(int index) +{ + QWidget *widget = ui->tabs->widget(index); + ui->tabs->removeTab(index); + delete widget; +} + +void SkyMapGUI::sendToRotator(const QString& name, double az, double alt) +{ + QList rotatorPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(m_skymap, "target", rotatorPipes); + + for (const auto& pipe : rotatorPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString(name)); + swgTarget->setAzimuth(az); + swgTarget->setElevation(alt); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(m_skymap, swgTarget)); + } +} + +void SkyMapGUI::updateSourceList(const QStringList& renameFrom, const QStringList& renameTo) +{ + m_availableChannelOrFeatures = m_availableChannelOrFeatureHandler.getAvailableChannelOrFeatureList(); + + // Update source settting if it has been renamed + if (renameFrom.contains(m_settings.m_source)) + { + m_settings.m_source = renameTo[renameFrom.indexOf(m_settings.m_source)]; + applySetting("source"); // Only call after m_availableChannelOrFeatures has been updated + } + + int prevIdx = ui->source->currentIndex(); + ui->source->blockSignals(true); + ui->source->clear(); + + for (const auto& item : m_availableChannelOrFeatures) { + ui->source->addItem(item.getLongId()); + } + + // Select current setting, if it exists + // If not, and no prior setting, make sure nothing selected, as channel/feature may be created later on + // If not found and something was previously selected, clear the setting, as probably deleted + int idx = ui->source->findText(m_settings.m_source); + if (idx >= 0) + { + ui->source->setCurrentIndex(idx); + ui->track->setEnabled(true); + } + else if (prevIdx == -1) + { + ui->source->setCurrentIndex(-1); + ui->track->setChecked(false); + ui->track->setEnabled(false); + } + else + { + m_settings.m_source = ""; + applySetting("source"); + } + + ui->source->blockSignals(false); + + // If no current settting, select first available + if (m_settings.m_source.isEmpty() && (ui->source->count() > 0)) + { + ui->source->setCurrentIndex(0); + on_source_currentIndexChanged(0); + } +} + +void SkyMapGUI::handlePipeMessageQueue(MessageQueue* messageQueue) +{ + Message* message; + + while ((message = messageQueue->pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} \ No newline at end of file diff --git a/plugins/feature/skymap/skymapgui.h b/plugins/feature/skymap/skymapgui.h new file mode 100644 index 000000000..efaff4168 --- /dev/null +++ b/plugins/feature/skymap/skymapgui.h @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // +// Copyright (C) 2022 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_SKYMAPGUI_H_ +#define INCLUDE_FEATURE_SKYMAPGUI_H_ + +#include +#include +#include +#include +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#endif +#include + +#include +#include + +#include "feature/featuregui.h" +#include "util/messagequeue.h" +#include "settings/rollupstate.h" +#include "availablechannelorfeaturehandler.h" +#include "maincore.h" + +#include "skymapsettings.h" +#include "webinterface.h" +#include "webserver.h" +#include "wtml.h" + +class PluginAPI; +class FeatureUISet; +class SkyMap; + +namespace Ui { + class SkyMapGUI; +} + +class SkyMapGUI; + +class SkyMapGUI : public FeatureGUI { + Q_OBJECT +public: + static SkyMapGUI* create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual void setWorkspaceIndex(int index); + virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; } + virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; } + virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; } + SkyMap *getSkyMap() { return m_skymap; } + +private: + Ui::SkyMapGUI* ui; + PluginAPI* m_pluginAPI; + FeatureUISet* m_featureUISet; + SkyMapSettings m_settings; + QList m_settingsKeys; + RollupState m_rollupState; + bool m_doApplySettings; + QObject *m_source; + AvailableChannelOrFeatureList m_availableChannelOrFeatures; + AvailableChannelOrFeatureHandler m_availableChannelOrFeatureHandler; + + SkyMap* m_skymap; + MessageQueue m_inputMessageQueue; + quint16 m_skymapTileServerPort; + + WebServer *m_webServer; + quint16 m_webPort; + WTML m_wtml; + WebInterface *m_webInterface; + + double m_ra; //!< Target from source plugin + double m_dec; + QDateTime m_dateTime; //!< Date time from source plugin + + QStringList m_wwtBackgrounds; + + explicit SkyMapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr); + virtual ~SkyMapGUI(); + + void blockApplySettings(bool block); + void applySetting(const QString& settingsKey); + void applySettings(const QStringList& settingsKeys, bool force = false); + void applyAllSettings(); + void displaySettings(); + bool handleMessage(const Message& message); + void makeUIConnections(); + + void setDateTime(QDateTime dateTime); + QDateTime getDateTime() const; + void setPosition(float latitude, float longitude, float altitude); + QGeoCoordinate getPosition() const; + void initSkyMap(); + QString backgroundID(const QString& name); + void updateBackgrounds(); + void updateToolbar(); + void updateProjection(); + void find(const QString& text); + void sendToRotator(const QString& name, double az, double alt); + +private slots: + void onMenuDialogCalled(const QPoint &p); + void onWidgetRolled(QWidget* widget, bool rollDown); + void handleInputMessages(); + void on_tabs_tabCloseRequested(int index); + void on_find_returnPressed(); + void on_displaySettings_clicked(); + void on_displayNames_clicked(bool checked); + void on_displayConstellations_clicked(bool checked); + void on_displayReticle_clicked(bool checked); + void on_displayGrid_clicked(bool checked); + void on_displayAntennaFoV_clicked(bool checked); + void on_map_currentIndexChanged(int index); + void on_background_currentIndexChanged(int index); + void on_projection_currentIndexChanged(int index); + void on_source_currentIndexChanged(int index); + void on_track_clicked(bool checked); + void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); + void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + void loadingChanged(const QWebEngineLoadingInfo &loadingInfo); +#endif + void preferenceChanged(int elementType); + void receivedEvent(const QJsonObject &obj); + void wtmlUpdated(const QList& dataSets); + void updateSourceList(const QStringList& renameFrom, const QStringList& renameTo); + void handlePipeMessageQueue(MessageQueue* messageQueue); + +}; + +#endif // INCLUDE_FEATURE_SKYMAPGUI_H_ diff --git a/plugins/feature/skymap/skymapgui.ui b/plugins/feature/skymap/skymapgui.ui new file mode 100644 index 000000000..4845b04a0 --- /dev/null +++ b/plugins/feature/skymap/skymapgui.ui @@ -0,0 +1,431 @@ + + + SkyMapGUI + + + + 0 + 0 + 881 + 293 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + Liberation Sans + 9 + + + + Qt::StrongFocus + + + SkyMap + + + + + 0 + 0 + 871 + 41 + + + + + 300 + 0 + + + + Settings + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + Find + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + Enter name of object to find + + + + + + + Sky map + + + + WWT + + + + + ESASky + + + + + Aladin + + + + + + + + + 180 + 0 + + + + Select background image set + + + + + + + Projection + + + + + + + Display names + + + ^ + + + + :/info.png:/info.png + + + true + + + true + + + + + + + Display constellations + + + + + + + :/skymap/icons/constellation.png:/skymap/icons/constellation.png + + + true + + + true + + + + + + + Display grid + + + ^ + + + + :/gridrect.png:/gridrect.png + + + true + + + true + + + + + + + Display reticle + + + ^ + + + + :/skymap/icons/reticle.png:/skymap/icons/reticle.png + + + true + + + true + + + + + + + Display antenna field-of-view + + + ^ + + + + :/antenna.png:/antenna.png + + + true + + + true + + + + + + + Track source + + + + + + + :/gridpolar.png:/gridpolar.png + + + true + + + true + + + + + + + + 120 + 0 + + + + Source feature to get target from + + + + F0:1 StarTracker + + + + + + + + Show settings dialog + + + + + + + :/listing.png:/listing.png + + + + + + + + + + + 10 + 60 + 591 + 211 + + + + + 0 + 0 + + + + SkyMap + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + true + + + + Map + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 100 + 100 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + RollupContents + QWidget +
gui/rollupcontents.h
+ 1 +
+ + QWebEngineView + QWidget +
QtWebEngineWidgets/QWebEngineView
+ 1 +
+ + WebView + QWebEngineView +
webview.h
+ 1 +
+
+ + find + background + displayNames + + + + + + +
diff --git a/plugins/feature/skymap/skymapplugin.cpp b/plugins/feature/skymap/skymapplugin.cpp new file mode 100644 index 000000000..c35b7ebf4 --- /dev/null +++ b/plugins/feature/skymap/skymapplugin.cpp @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2023 Edouard Griffiths, F4EXB // +// Copyright (C) 2019 Davide Gerhard // +// Copyright (C) 2020-2023 Jon Beniston, M7RCE // +// Copyright (C) 2020 Kacper Michajłow // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + + +#include +#include "plugin/pluginapi.h" + +#ifndef SERVER_MODE +#include "skymapgui.h" +#endif +#include "skymap.h" +#include "skymapplugin.h" +#include "skymapwebapiadapter.h" + +const PluginDescriptor SkyMapPlugin::m_pluginDescriptor = { + SkyMap::m_featureId, + QStringLiteral("Sky Map"), + QStringLiteral("7.18.0"), + QStringLiteral("(c) Jon Beniston, M7RCE"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +SkyMapPlugin::SkyMapPlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(nullptr) +{ +} + +const PluginDescriptor& SkyMapPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void SkyMapPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + m_pluginAPI->registerFeature(SkyMap::m_featureIdURI, SkyMap::m_featureId, this); +} + +#ifdef SERVER_MODE +FeatureGUI* SkyMapPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + (void) featureUISet; + (void) feature; + return nullptr; +} +#else +FeatureGUI* SkyMapPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const +{ + return SkyMapGUI::create(m_pluginAPI, featureUISet, feature); +} +#endif + +Feature* SkyMapPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const +{ + return new SkyMap(webAPIAdapterInterface); +} + +FeatureWebAPIAdapter* SkyMapPlugin::createFeatureWebAPIAdapter() const +{ + return new SkyMapWebAPIAdapter(); +} diff --git a/plugins/feature/skymap/skymapplugin.h b/plugins/feature/skymap/skymapplugin.h new file mode 100644 index 000000000..8c8ea3bf4 --- /dev/null +++ b/plugins/feature/skymap/skymapplugin.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB // +// Copyright (C) 2015 John Greb // +// Copyright (C) 2020-2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_SKYMAPPLUGIN_H +#define INCLUDE_FEATURE_SKYMAPPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class FeatureGUI; +class WebAPIAdapterInterface; + +class SkyMapPlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.feature.skymap") + +public: + explicit SkyMapPlugin(QObject* parent = nullptr); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual FeatureGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const; + virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const; + virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif // INCLUDE_FEATURE_SKYMAPPLUGIN_H diff --git a/plugins/feature/skymap/skymapsettings.cpp b/plugins/feature/skymap/skymapsettings.cpp new file mode 100644 index 000000000..56bc21b65 --- /dev/null +++ b/plugins/feature/skymap/skymapsettings.cpp @@ -0,0 +1,361 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2017, 2019-2020, 2022 Edouard Griffiths, F4EXB // +// Copyright (C) 2020-2024 Jon Beniston, M7RCE // +// Copyright (C) 2022 CRD716 // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "util/simpleserializer.h" +#include "util/httpdownloadmanager.h" +#include "settings/serializable.h" + +#include "skymapsettings.h" + +const QStringList SkyMapSettings::m_pipeTypes = { + QStringLiteral("StarTracker"), + QStringLiteral("SatelliteTracker"), + QStringLiteral("GS232Controller"), + QStringLiteral("Map") +}; + +const QStringList SkyMapSettings::m_pipeURIs = { + QStringLiteral("sdrangel.feature.startracker"), + QStringLiteral("sdrangel.feature.satellitetracker"), + QStringLiteral("sdrangel.feature.gs232controller"), + QStringLiteral("sdrangel.feature.map") +}; + +SkyMapSettings::SkyMapSettings() : + m_rollupState(nullptr) +{ + resetToDefaults(); +} + +SkyMapSettings::~SkyMapSettings() +{ +} + +void SkyMapSettings::resetToDefaults() +{ + m_map = "WWT"; + m_displayNames = true; + m_displayConstellations = true; + m_displayReticle = true; + m_displayGrid = false; + m_displayAntennaFoV = false; + m_projection = ""; + m_source = ""; + m_track = false; + m_hpbw = 10.0f; + m_latitude = 0.0f; + m_longitude = 0.0f; + m_altitude = 0.0f; + m_useMyPosition = false; + m_wwtSettings = QHash({ + {"constellationBoundaries", false}, + {"constellationFigures", true}, + {"constellationLabels", true}, + {"constellationPictures", false}, + {"constellationSelection", false}, + {"ecliptic", false}, + {"eclipticOverviewText", false}, + {"eclipticGrid", false}, + {"eclipticGridText", true}, + {"altAzGrid", true}, + {"altAzGridText", true}, + {"galacticGrid", false}, + {"galacticGridText", true}, + {"elevationModel", false}, + {"earthSky", false}, + {"horizon", false}, + {"iss", false}, + {"precessionChart", false}, + {"skyGrids", false}, + {"skyNode", false}, + {"skyOverlays", false}, + {"solarSystemCosmos", false}, + {"solarSystemLighting", true}, + {"solarSystemMilkyWay", true}, + {"solarSystemMinorOrbits", false}, + {"solarSystemMinorPlanets", false}, + {"solarSystemMultiRes", true}, + {"solarSystemOrbits", true}, + {"solarSystemOverlays", false}, + {"solarSystemPlanets", true}, + {"solarSystemStars", true}, + + }); + m_title = "Sky Map"; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIFeatureSetIndex = 0; + m_reverseAPIFeatureIndex = 0; + m_workspaceIndex = 0; +} + +QByteArray SkyMapSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeString(2, m_map); + s.writeBool(1, m_displayNames); + s.writeBool(15, m_displayConstellations); + s.writeBool(17, m_displayReticle); + s.writeBool(18, m_displayGrid); + s.writeBool(21, m_displayAntennaFoV); + s.writeString(3, m_projection); + s.writeString(4, m_source); + s.writeBool(20, m_track); + s.writeFloat(22, m_hpbw); + s.writeFloat(23, m_latitude); + s.writeFloat(24, m_longitude); + s.writeFloat(25, m_altitude); + s.writeBool(26, m_useMyPosition); + s.writeHash(27, m_wwtSettings); + + s.writeString(8, m_title); + s.writeU32(9, m_rgbColor); + s.writeBool(10, m_useReverseAPI); + s.writeString(11, m_reverseAPIAddress); + s.writeU32(12, m_reverseAPIPort); + s.writeU32(13, m_reverseAPIFeatureSetIndex); + s.writeU32(14, m_reverseAPIFeatureIndex); + + if (m_rollupState) { + s.writeBlob(19, m_rollupState->serialize()); + } + + s.writeS32(33, m_workspaceIndex); + s.writeBlob(34, m_geometryBytes); + + return s.final(); +} + +bool SkyMapSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + QByteArray bytetmp; + uint32_t utmp; + QString strtmp; + QByteArray blob; + QString string; + + d.readString(2, &m_map, "WWT"); + d.readBool(1, &m_displayNames, true); + d.readBool(15, &m_displayConstellations, true); + d.readBool(17, &m_displayReticle, true); + d.readBool(18, &m_displayGrid, true); + d.readBool(21, &m_displayAntennaFoV, true); + d.readString(3, &m_projection, ""); + d.readString(4, &m_source, ""); + d.readBool(20, &m_track, false); + d.readFloat(22, &m_hpbw, 10.0f); + d.readFloat(23, &m_latitude, 0.0f); + d.readFloat(24, &m_longitude, 0.0f); + d.readFloat(25, &m_altitude, 0.0f); + d.readBool(26, &m_useMyPosition, false); + d.readHash(27, &m_wwtSettings); + + d.readString(8, &m_title, "Sky Map"); + d.readU32(9, &m_rgbColor, QColor(225, 25, 99).rgba()); + d.readBool(10, &m_useReverseAPI, false); + d.readString(11, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(12, &utmp, 0); + + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(13, &utmp, 0); + m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp; + d.readU32(14, &utmp, 0); + m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp; + + if (m_rollupState) + { + d.readBlob(19, &bytetmp); + m_rollupState->deserialize(bytetmp); + } + + d.readS32(33, &m_workspaceIndex, 0); + d.readBlob(34, &m_geometryBytes); + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +void SkyMapSettings::applySettings(const QStringList& settingsKeys, const SkyMapSettings& settings) +{ + if (settingsKeys.contains("map")) { + m_map = settings.m_map; + } + if (settingsKeys.contains("displayNames")) { + m_displayNames = settings.m_displayNames; + } + if (settingsKeys.contains("displayConstellations")) { + m_displayConstellations = settings.m_displayConstellations; + } + if (settingsKeys.contains("displayReticle")) { + m_displayReticle = settings.m_displayReticle; + } + if (settingsKeys.contains("displayGrid")) { + m_displayGrid = settings.m_displayGrid; + } + if (settingsKeys.contains("displayAntennaFoV")) { + m_displayAntennaFoV = settings.m_displayAntennaFoV; + } + if (settingsKeys.contains("background")) { + m_background = settings.m_background; + } + if (settingsKeys.contains("projection")) { + m_projection = settings.m_projection; + } + if (settingsKeys.contains("source")) { + m_source = settings.m_source; + } + if (settingsKeys.contains("track")) { + m_track = settings.m_track; + } + if (settingsKeys.contains("hpbw")) { + m_hpbw = settings.m_hpbw; + } + if (settingsKeys.contains("latitude")) { + m_latitude = settings.m_latitude; + } + if (settingsKeys.contains("longitude")) { + m_longitude = settings.m_longitude; + } + if (settingsKeys.contains("altitude")) { + m_altitude = settings.m_altitude; + } + if (settingsKeys.contains("useMyPosition")) { + m_useMyPosition = settings.m_useMyPosition; + } + if (settingsKeys.contains("title")) { + m_title = settings.m_title; + } + 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; + } +} + +QString SkyMapSettings::getDebugString(const QStringList& settingsKeys, bool force) const +{ + std::ostringstream ostr; + + if (settingsKeys.contains("map") || force) { + ostr << " m_map: " << m_map.toStdString(); + } + if (settingsKeys.contains("displayNames") || force) { + ostr << " m_displayNames: " << m_displayNames; + } + if (settingsKeys.contains("displayConstellations") || force) { + ostr << " m_displayConstellations: " << m_displayConstellations; + } + if (settingsKeys.contains("displayReticle") || force) { + ostr << " m_displayReticle: " << m_displayReticle; + } + if (settingsKeys.contains("displayAntennaFoV") || force) { + ostr << " m_displayAntennaFoV: " << m_displayAntennaFoV; + } + if (settingsKeys.contains("background") || force) { + ostr << " m_background: " << m_background.toStdString(); + } + if (settingsKeys.contains("projection") || force) { + ostr << " m_projection: " << m_projection.toStdString(); + } + if (settingsKeys.contains("source") || force) { + ostr << " m_source: " << m_source.toStdString(); + } + if (settingsKeys.contains("track") || force) { + ostr << " m_track: " << m_track; + } + if (settingsKeys.contains("hpbw") || force) { + ostr << " m_hpbw: " << m_hpbw; + } + if (settingsKeys.contains("latitude") || force) { + ostr << " m_latitude: " << m_latitude; + } + if (settingsKeys.contains("longitude") || force) { + ostr << " m_longitude: " << m_longitude; + } + if (settingsKeys.contains("altitude") || force) { + ostr << " m_altitude: " << m_altitude; + } + if (settingsKeys.contains("useMyPosition") || force) { + ostr << " m_useMyPosition: " << m_useMyPosition; + } + if (settingsKeys.contains("title") || force) { + ostr << " m_title: " << m_title.toStdString(); + } + if (settingsKeys.contains("useReverseAPI") || force) { + ostr << " m_useReverseAPI: " << m_useReverseAPI; + } + if (settingsKeys.contains("reverseAPIAddress") || 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; + } + + return QString(ostr.str().c_str()); +} + diff --git a/plugins/feature/skymap/skymapsettings.h b/plugins/feature/skymap/skymapsettings.h new file mode 100644 index 000000000..5731fde16 --- /dev/null +++ b/plugins/feature/skymap/skymapsettings.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2020, 2022 Edouard Griffiths, F4EXB // +// Copyright (C) 2020-2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_SKYMAPSETTINGS_H_ +#define INCLUDE_FEATURE_SKYMAPSETTINGS_H_ + +#include +#include +#include + +class Serializable; + +struct SkyMapSettings +{ + QString m_map; //!< "WWT", "ESASky" or "Aladin" + bool m_displayNames; + bool m_displayConstellations; + bool m_displayReticle; + bool m_displayGrid; + bool m_displayAntennaFoV; + QString m_background; + QString m_projection; + QString m_source; //!< Plugin to get target coords from + bool m_track; //!< Track source + float m_hpbw; //!< Antenna HPBW + float m_latitude; //!< Antenna position + float m_longitude; + float m_altitude; + bool m_useMyPosition; + QHash m_wwtSettings; //!< WWT specific settings + + QString m_title; + quint32 m_rgbColor; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIFeatureSetIndex; + uint16_t m_reverseAPIFeatureIndex; + Serializable *m_rollupState; + int m_workspaceIndex; + QByteArray m_geometryBytes; + + SkyMapSettings(); + ~SkyMapSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } + void applySettings(const QStringList& settingsKeys, const SkyMapSettings& settings); + QString getDebugString(const QStringList& settingsKeys, bool force=false) const; + + static const QStringList m_pipeTypes; + static const QStringList m_pipeURIs; + +}; + +#endif // INCLUDE_FEATURE_SKYMAPSETTINGS_H_ + diff --git a/plugins/feature/skymap/skymapsettingsdialog.cpp b/plugins/feature/skymap/skymapsettingsdialog.cpp new file mode 100644 index 000000000..2ed2e4296 --- /dev/null +++ b/plugins/feature/skymap/skymapsettingsdialog.cpp @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "skymapsettingsdialog.h" + +SkyMapSettingsDialog::SkyMapSettingsDialog(SkyMapSettings *settings, QWidget* parent) : + QDialog(parent), + m_settings(settings), + ui(new Ui::SkyMapSettingsDialog) +{ + ui->setupUi(this); + + ui->hpbw->setValue(m_settings->m_hpbw); + ui->latitude->setText(QString::number(m_settings->m_latitude, 'f', 6)); + ui->longitude->setText(QString::number(m_settings->m_longitude, 'f', 6)); + ui->altitude->setValue(m_settings->m_altitude); + ui->useMyPosition->setChecked(m_settings->m_useMyPosition); + + // WWT + ui->constellationBoundaries->setChecked(m_settings->m_wwtSettings.value("constellationBoundaries").toBool()); + ui->constellationFigures->setChecked(m_settings->m_wwtSettings.value("constellationFigures").toBool()); + ui->constellationLabels->setChecked(m_settings->m_wwtSettings.value("constellationLabels").toBool()); + ui->constellationPictures->setChecked(m_settings->m_wwtSettings.value("constellationPictures").toBool()); + ui->constellationSelection->setChecked(m_settings->m_wwtSettings.value("constellationSelection").toBool()); + + ui->ecliptic->setChecked(m_settings->m_wwtSettings.value("ecliptic").toBool()); + ui->eclipticOverviewText->setChecked(m_settings->m_wwtSettings.value("eclipticOverviewText").toBool()); + ui->eclipticGrid->setChecked(m_settings->m_wwtSettings.value("eclipticGrid").toBool()); + ui->eclipticGridText->setChecked(m_settings->m_wwtSettings.value("eclipticGridText").toBool()); + ui->altAzGrid->setChecked(m_settings->m_wwtSettings.value("altAzGrid").toBool()); + ui->altAzGridText->setChecked(m_settings->m_wwtSettings.value("altAzGridText").toBool()); + ui->equatorialGrid->setChecked(m_settings->m_wwtSettings.value("equatorialGrid").toBool()); + ui->equatorialGridText->setChecked(m_settings->m_wwtSettings.value("equatorialGridText").toBool()); + ui->galacticGrid->setChecked(m_settings->m_wwtSettings.value("galacticGrid").toBool()); + ui->galacticGridText->setChecked(m_settings->m_wwtSettings.value("galacticGridText").toBool()); + ui->precessionChart->setChecked(m_settings->m_wwtSettings.value("precessionChart").toBool()); + + ui->solarSystemCosmos->setChecked(m_settings->m_wwtSettings.value("solarSystemCosmos").toBool()); + ui->solarSystemLighting->setChecked(m_settings->m_wwtSettings.value("solarSystemLighting").toBool()); + ui->solarSystemMilkyWay->setChecked(m_settings->m_wwtSettings.value("solarSystemMilkyWay").toBool()); + ui->solarSystemMinorOrbits->setChecked(m_settings->m_wwtSettings.value("solarSystemMinorOrbits").toBool()); + ui->solarSystemMinorPlanets->setChecked(m_settings->m_wwtSettings.value("solarSystemMinorPlanets").toBool()); + ui->solarSystemMultiRes->setChecked(m_settings->m_wwtSettings.value("solarSystemMultiRes").toBool()); + ui->solarSystemOrbits->setChecked(m_settings->m_wwtSettings.value("solarSystemOrbits").toBool()); + //ui->solarSystemOverlays->setChecked(m_settings->m_wwtSettings.value("solarSystemOverlays").toBool()); + ui->solarSystemPlanets->setChecked(m_settings->m_wwtSettings.value("solarSystemPlanets").toBool()); + ui->solarSystemStars->setChecked(m_settings->m_wwtSettings.value("solarSystemStars").toBool()); + + ui->iss->setChecked(m_settings->m_wwtSettings.value("iss").toBool()); +} + +SkyMapSettingsDialog::~SkyMapSettingsDialog() +{ + delete ui; +} + +void SkyMapSettingsDialog::accept() +{ + QDialog::accept(); + + if (m_settings->m_hpbw != ui->hpbw->value()) + { + m_settings->m_hpbw = ui->hpbw->value(); + m_settingsKeysChanged.append("hpbw"); + } + if (m_settings->m_latitude != ui->latitude->text().toFloat()) + { + m_settings->m_latitude = ui->latitude->text().toFloat(); + m_settingsKeysChanged.append("latitude"); + } + if (m_settings->m_longitude != ui->longitude->text().toFloat()) + { + m_settings->m_longitude = ui->longitude->text().toFloat(); + m_settingsKeysChanged.append("longitude"); + } + if (m_settings->m_altitude != ui->altitude->value()) + { + m_settings->m_altitude = ui->altitude->value(); + m_settingsKeysChanged.append("altitude"); + } + if (m_settings->m_useMyPosition != ui->useMyPosition->isChecked()) + { + m_settings->m_useMyPosition = ui->useMyPosition->isChecked(); + m_settingsKeysChanged.append("useMyPosition"); + } + + m_settings->m_wwtSettings.insert("constellationBoundaries", ui->constellationBoundaries->isChecked()); + m_settings->m_wwtSettings.insert("constellationFigures", ui->constellationFigures->isChecked()); + m_settings->m_wwtSettings.insert("constellationLabels", ui->constellationLabels->isChecked()); + m_settings->m_wwtSettings.insert("constellationPictures", ui->constellationPictures->isChecked()); + m_settings->m_wwtSettings.insert("constellationSelection", ui->constellationSelection->isChecked()); + + m_settings->m_wwtSettings.insert("ecliptic", ui->ecliptic->isChecked()); + m_settings->m_wwtSettings.insert("eclipticOverviewText", ui->eclipticOverviewText->isChecked()); + m_settings->m_wwtSettings.insert("eclipticGrid", ui->eclipticGrid->isChecked()); + m_settings->m_wwtSettings.insert("eclipticGridText", ui->eclipticGridText->isChecked()); + m_settings->m_wwtSettings.insert("altAzGrid", ui->altAzGrid->isChecked()); + m_settings->m_wwtSettings.insert("altAzGridText", ui->altAzGridText->isChecked()); + m_settings->m_wwtSettings.insert("equatorialGrid", ui->equatorialGrid->isChecked()); + m_settings->m_wwtSettings.insert("equatorialGridText", ui->equatorialGridText->isChecked()); + m_settings->m_wwtSettings.insert("galacticGrid", ui->galacticGrid->isChecked()); + m_settings->m_wwtSettings.insert("galacticGridText", ui->galacticGridText->isChecked()); + m_settings->m_wwtSettings.insert("precessionChart", ui->precessionChart->isChecked()); + + m_settings->m_wwtSettings.insert("solarSystemCosmos", ui->solarSystemCosmos->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemLighting", ui->solarSystemLighting->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemMilkyWay", ui->solarSystemMilkyWay->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemMinorOrbits", ui->solarSystemMinorOrbits->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemMinorPlanets", ui->solarSystemMinorPlanets->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemMultiRes", ui->solarSystemMultiRes->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemOrbits", ui->solarSystemOrbits->isChecked()); + //m_settings->m_wwtSettings.insert("solarSystemOverlays", ui->solarSystemOverlays->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemPlanets", ui->solarSystemPlanets->isChecked()); + m_settings->m_wwtSettings.insert("solarSystemStars", ui->solarSystemStars->isChecked()); + + m_settings->m_wwtSettings.insert("iss", ui->iss->isChecked()); + + m_settingsKeysChanged.append("wwtSettings"); // Being lazy here +} + +void SkyMapSettingsDialog::on_constellationBoundaries_toggled(bool checked) +{ + ui->constellationSelection->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_ecliptic_toggled(bool checked) +{ + ui->eclipticOverviewText->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_eclipticGrid_toggled(bool checked) +{ + ui->eclipticGridText->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_altAzGrid_toggled(bool checked) +{ + ui->altAzGridText->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_equatorialGrid_toggled(bool checked) +{ + ui->equatorialGridText->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_galacticGrid_toggled(bool checked) +{ + ui->galacticGridText->setEnabled(checked); +} + +void SkyMapSettingsDialog::on_useMyPosition_toggled(bool checked) +{ + ui->latitude->setEnabled(!checked); + ui->latitudeLabel->setEnabled(!checked); + ui->longitude->setEnabled(!checked); + ui->longitudeLabel->setEnabled(!checked); + ui->altitude->setEnabled(!checked); + ui->altitudeLabel->setEnabled(!checked); +} diff --git a/plugins/feature/skymap/skymapsettingsdialog.h b/plugins/feature/skymap/skymapsettingsdialog.h new file mode 100644 index 000000000..710520082 --- /dev/null +++ b/plugins/feature/skymap/skymapsettingsdialog.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_SKYMAPSETTINGSDIALOG_H +#define INCLUDE_FEATURE_SKYMAPSETTINGSDIALOG_H + +#include +#include +#include + +#include "ui_skymapsettingsdialog.h" +#include "skymapsettings.h" + +class SkyMapSettingsDialog : public QDialog { + Q_OBJECT + +public: + explicit SkyMapSettingsDialog(SkyMapSettings *settings, QWidget* parent = 0); + ~SkyMapSettingsDialog(); + +public: + QStringList m_settingsKeysChanged; // List of setting keys that have been changed + +private: + SkyMapSettings *m_settings; + +private slots: + void accept(); + void on_constellationBoundaries_toggled(bool checked); + void on_ecliptic_toggled(bool checked); + void on_eclipticGrid_toggled(bool checked); + void on_altAzGrid_toggled(bool checked); + void on_equatorialGrid_toggled(bool checked); + void on_galacticGrid_toggled(bool checked); + void on_useMyPosition_toggled(bool checked); + +private: + Ui::SkyMapSettingsDialog* ui; + +}; + +#endif // INCLUDE_FEATURE_SKYMAPSETTINGSDIALOG_H diff --git a/plugins/feature/skymap/skymapsettingsdialog.ui b/plugins/feature/skymap/skymapsettingsdialog.ui new file mode 100644 index 000000000..6e5a92269 --- /dev/null +++ b/plugins/feature/skymap/skymapsettingsdialog.ui @@ -0,0 +1,480 @@ + + + SkyMapSettingsDialog + + + + 0 + 0 + 441 + 671 + + + + + 9 + + + + SkyMap Display Settings + + + + + + + 0 + + + + + 0 + + + + Settings + + + + + + Use observation location from Preferences > My Position + + + + + + + Latitude (°) + + + + + + + Longitude (°) + + + + + + + Altitude (m) + + + + + + + Antenna/observation altitude in metres + + + -100 + + + 10000 + + + + + + + HPBW (°) + + + + + + + Antenna half-power beamwidth in degrees + + + 0.010000000000000 + + + 360.000000000000000 + + + + + + + Latitude of antenna/observation location in degrees. North positive + + + + + + + Longitude of antenna/observation location in degrees. East positive + + + + + + + + WWT + + + + + + Grids + + + + + + + 160 + 0 + + + + Ecliptic + + + + + + + Ecliptic Grid + + + + + + + false + + + Ecliptic Overview Text + + + + + + + false + + + Ecliptic Grid Text + + + + + + + Alt Az Grid + + + + + + + false + + + Alt Az Grid Text + + + + + + + Equatorial Grid + + + + + + + false + + + Equatorial Grid Text + + + + + + + Galactic Grid + + + + + + + false + + + Galactic Grid Text + + + + + + + Precession Chart + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Constellations + + + + + + Display constellation stick figures + + + Figures + + + + + + + + 160 + 0 + + + + Display boundaries between constellations + + + Boundaries + + + + + + + Displays boundary only for constellation at the center of view + + + Centre boundary only + + + + + + + Display constellation names + + + Labels + + + + + + + Display constellation pictures + + + Pictures + + + + + + + + + + Display ISS model + + + ISS + + + + + + + Settings that apply only to the Solar System view + + + Solar System View + + + + + + + 160 + 0 + + + + Displays cosmos (when zoomed far out) + + + Cosmos + + + + + + + Displays Milky Way + + + Milky Way + + + + + + + Displays stars + + + Stars + + + + + + + Displays planets + + + Planets + + + + + + + Displays asteroids + + + Asteroids + + + + + + + Displays planetary orbits + + + Planetary Orbits + + + + + + + Displays orbits of moons and minor satellites + + + Moon and Satellite Orbits + + + + + + + Applies lighting and shadows to planets + + + Lighting and Shadows + + + + + + + Uses higher resolution planetary imagery when zooming in + + + Mulit Res Planets + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + buttonBox + accepted() + SkyMapSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SkyMapSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/feature/skymap/skymapwebapiadapter.cpp b/plugins/feature/skymap/skymapwebapiadapter.cpp new file mode 100644 index 000000000..15b9bb537 --- /dev/null +++ b/plugins/feature/skymap/skymapwebapiadapter.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGFeatureSettings.h" +#include "skymap.h" +#include "skymapwebapiadapter.h" + +SkyMapWebAPIAdapter::SkyMapWebAPIAdapter() +{} + +SkyMapWebAPIAdapter::~SkyMapWebAPIAdapter() +{} + +int SkyMapWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSkyMapSettings(new SWGSDRangel::SWGSkyMapSettings()); + response.getSkyMapSettings()->init(); + SkyMap::webapiFormatFeatureSettings(response, m_settings); + + return 200; +} + +int SkyMapWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage) +{ + (void) force; // no action + (void) errorMessage; + SkyMap::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response); + + return 200; +} diff --git a/plugins/feature/skymap/skymapwebapiadapter.h b/plugins/feature/skymap/skymapwebapiadapter.h new file mode 100644 index 000000000..fae3e597c --- /dev/null +++ b/plugins/feature/skymap/skymapwebapiadapter.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019-2020 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_SKYMAP_WEBAPIADAPTER_H +#define INCLUDE_SKYMAP_WEBAPIADAPTER_H + +#include "feature/featurewebapiadapter.h" +#include "skymapsettings.h" + +/** + * Standalone API adapter only for the settings + */ +class SkyMapWebAPIAdapter : public FeatureWebAPIAdapter { +public: + SkyMapWebAPIAdapter(); + virtual ~SkyMapWebAPIAdapter(); + + virtual QByteArray serialize() const { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& featureSettingsKeys, + SWGSDRangel::SWGFeatureSettings& response, + QString& errorMessage); + +private: + SkyMapSettings m_settings; +}; + +#endif // INCLUDE_SKYMAP_WEBAPIADAPTER_H diff --git a/plugins/feature/skymap/webinterface.cpp b/plugins/feature/skymap/webinterface.cpp new file mode 100644 index 000000000..e929849e6 --- /dev/null +++ b/plugins/feature/skymap/webinterface.cpp @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "webinterface.h" + +WebInterface::WebInterface(QObject *parent) : + WebSocketServer(parent) +{ +} + +// Set the current camera view to a given coordinates +void WebInterface::setView(double ra, double dec, float zoom) +{ + QJsonObject obj { + {"command", "setView"}, + {"ra", ra}, + {"dec", dec}, + {"zoom", zoom} + }; + send(obj); +} + +// Set observation position +void WebInterface::setPosition(const QGeoCoordinate& position) +{ + QJsonObject obj { + {"command", "setPosition"}, + {"latitude", position.latitude()}, + {"longitude", position.longitude()}, + {"altitude", position.altitude()} + }; + send(obj); +} + +// Set date and time +void WebInterface::setDateTime(QDateTime dateTime) +{ + QJsonObject obj { + {"command", "setDateTime"}, + {"dateTime", dateTime.toUTC().toString(Qt::ISODateWithMs)} + }; + send(obj); +} + +// Set the camera to track the item with the specified name +void WebInterface::track(const QString& name) +{ + QJsonObject obj { + {"command", "track"}, + {"name", name} + }; + send(obj); +} + +void WebInterface::setBackground(const QString &background) +{ + QJsonObject obj { + {"command", "setBackground"}, + {"background", background}, + }; + send(obj); +} + +void WebInterface::setProjection(const QString &projection) +{ + QJsonObject obj { + {"command", "setProjection"}, + {"projection", projection}, + }; + send(obj); +} + +void WebInterface::showConstellations(bool show) +{ + QJsonObject obj { + {"command", "showConstellations"}, + {"show", show} + }; + send(obj); +} + +void WebInterface::showReticle(bool show) +{ + QJsonObject obj { + {"command", "showReticle"}, + {"show", show} + }; + send(obj); +} + +void WebInterface::showGrid(bool show) +{ + QJsonObject obj { + {"command", "showGrid"}, + {"show", show} + }; + send(obj); +} + +void WebInterface::showNames(bool show) +{ + QJsonObject obj { + {"command", "showNames"}, + {"show", show} + }; + send(obj); +} + +void WebInterface::showAntennaFoV(bool show) +{ + QJsonObject obj { + {"command", "showAntennaFoV"}, + {"show", show} + }; + send(obj); +} + +void WebInterface::setAntennaFoV(float hpbw) +{ + QJsonObject obj { + {"command", "setAntennaFoV"}, + {"hpbw", hpbw} + }; + send(obj); +} + +void WebInterface::setWWTSettings(const QHash& settings) +{ + QJsonObject obj { + {"command", "setWWTSettings"}, + }; + + QHashIterator itr(settings); + while (itr.hasNext()) + { + itr.next(); + QString key = itr.key(); + QVariant value = itr.value(); + obj.insert(key, value.toString()); + } + + send(obj); +} diff --git a/plugins/feature/skymap/webinterface.h b/plugins/feature/skymap/webinterface.h new file mode 100644 index 000000000..b339d9b5a --- /dev/null +++ b/plugins/feature/skymap/webinterface.h @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_WEBINTERFACE_H_ +#define INCLUDE_FEATURE_WEBINTERFACE_H_ + +#include + +#include "websocketserver.h" + +// Interface between C++ code and Web page via Web Socket using JSON +class WebInterface : public WebSocketServer +{ +public: + + WebInterface(QObject *parent = nullptr); + void setView(double ra, double dec, float zoom=1.0f); + void setPosition(const QGeoCoordinate& position); + void setDateTime(QDateTime dateTime); + void track(const QString &name); + void setBackground(const QString& name); + void setProjection(const QString& name); + void showConstellations(bool show); + void showReticle(bool show); + void showGrid(bool show); + void showAntennaFoV(bool show); + void showNames(bool show); + void setAntennaFoV(float hpbw); + void setWWTSettings(const QHash& settings); + +}; + +#endif // INCLUDE_FEATURE_WEBINTERFACE_H_ diff --git a/plugins/feature/skymap/webserver.cpp b/plugins/feature/skymap/webserver.cpp new file mode 100644 index 000000000..1adb1b966 --- /dev/null +++ b/plugins/feature/skymap/webserver.cpp @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022-2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "webserver.h" + +// port - port to listen on / is listening on. Use 0 for any free port. +WebServer::WebServer(quint16 &port, QObject* parent) : + QTcpServer(parent), + m_defaultMimeType("application/octet-stream") +{ + listen(QHostAddress::Any, port); + port = serverPort(); + qDebug() << "WebServer on port " << port; + + m_mimeTypes.insert(".html", new MimeType("text/html; charset=\"utf-8\"", false)); + m_mimeTypes.insert(".png", new MimeType("image/png")); + m_mimeTypes.insert(".glb", new MimeType("model/gltf-binary")); + m_mimeTypes.insert(".glbe", new MimeType("model/gltf-binary")); + m_mimeTypes.insert(".js", new MimeType("text/javascript")); + m_mimeTypes.insert(".css", new MimeType("text/css")); + m_mimeTypes.insert(".json", new MimeType("application/json")); + m_mimeTypes.insert(".geojson", new MimeType("application/geo+json")); +} + +void WebServer::incomingConnection(qintptr socket) +{ + QTcpSocket* s = new QTcpSocket(this); + connect(s, SIGNAL(readyRead()), this, SLOT(readClient())); + connect(s, SIGNAL(disconnected()), this, SLOT(discardClient())); + s->setSocketDescriptor(socket); + //addPendingConnection(socket); +} + +// Don't include leading or trailing / in from +void WebServer::addPathSubstitution(const QString &from, const QString &to) +{ + qDebug() << "Mapping " << from << " to " << to; + m_pathSubstitutions.insert(from, to); +} + +void WebServer::addSubstitution(QString path, QString from, QString to) +{ + Substitution *s = new Substitution(from, to); + if (m_substitutions.contains(path)) + { + QList *list = m_substitutions.value(path); + QMutableListIterator i(*list); + while (i.hasNext()) { + Substitution *sub = i.next(); + if (sub->m_from == from) { + i.remove(); + delete sub; + } + } + list->append(s); + } + else + { + QList *list = new QList(); + list->append(s); + m_substitutions.insert(path, list); + } +} + +QString WebServer::substitute(QString path, QString html) +{ + QList *list = m_substitutions.value(path); + for (const auto s : *list) { + html = html.replace(s->m_from, s->m_to); + } + return html; +} + +void WebServer::addFile(const QString &path, const QByteArray &data) +{ + m_files.insert(path, data); +} + +void WebServer::sendFile(QTcpSocket* socket, const QByteArray &data, MimeType *mimeType, const QString &path) +{ + QString header = QString("HTTP/1.0 200 Ok\r\nContent-Type: %1\r\nAccess-Control-Allow-Origin \"*\"\r\n\r\n").arg(mimeType->m_type); + if (mimeType->m_binary) + { + // Send file as binary + QByteArray headerUtf8 = header.toUtf8(); + socket->write(headerUtf8); + socket->write(data); + } + else + { + // Send file as text + QString html = QString(data); + // Make any substitutions in the content of the file + if (m_substitutions.contains(path)) { + html = substitute(path, html); + } + QTextStream os(socket); + os.setAutoDetectUnicode(true); + os << header << html; + } +} + +void WebServer::readClient() +{ + QTcpSocket* socket = (QTcpSocket*)sender(); + if (socket->canReadLine()) + { + QString line = socket->readLine(); + //qDebug() << "WebServer HTTP Request: " << line; + + QStringList tokens = QString(line).split(QRegularExpression("[ \r\n][ \r\n]*")); + if (tokens[0] == "GET") + { + // Get file type from extension + QString path = tokens[1]; + MimeType *mimeType = &m_defaultMimeType; + int extensionIdx = path.lastIndexOf("."); + if (extensionIdx != -1) { + QString extension = path.mid(extensionIdx); + if (m_mimeTypes.contains(extension)) { + mimeType = m_mimeTypes[extension]; + } + } + + // Try skymapping path + QStringList dirs = path.split('/'); + if ((dirs.length() >= 2) && m_pathSubstitutions.contains(dirs[1])) + { + dirs[1] = m_pathSubstitutions.value(dirs[1]); + dirs.removeFirst(); + QString newPath = dirs.join('/'); + //qDebug() << "SkyMapping " << path << " to " << newPath; + path = newPath; + } + + // See if we can find the file in our resources + QResource res(path); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + if (res.isValid() && (res.uncompressedSize() > 0)) + { + QByteArray data = res.uncompressedData(); + sendFile(socket, data, mimeType, path); + } +#else + if (res.isValid() && (res.size() > 0)) + { + QByteArray data = QByteArray::fromRawData((const char *)res.data(), res.size()); + if (res.isCompressed()) { + data = qUncompress(data); + } + sendFile(socket, data, mimeType, path); + } +#endif + else if (m_files.contains(path)) + { + // Path is a file held in memory + sendFile(socket, m_files.value(path).data(), mimeType, path); + } + else + { + // See if we can find a file on disk + QFile file(path); + if (file.open(QIODevice::ReadOnly)) + { + QByteArray data = file.readAll(); + if (path.endsWith(".glbe")) { + for (int i = 0; i < data.size(); i++) { + data[i] = data[i] ^ 0x55; + } + } + sendFile(socket, data, mimeType, path); + } + else + { + qDebug() << "WebServer " << path << " not found"; + // File not found + QTextStream os(socket); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Not Found\r\n" + "Content-Type: text/html; charset=\"utf-8\"\r\n" + "\r\n" + "\n" + "\n" + "

404 Not Found

\n" + "\n" + "\n"; + } + } + + socket->close(); + + if (socket->state() == QTcpSocket::UnconnectedState) { + delete socket; + } + } + } +} + +void WebServer::discardClient() +{ + QTcpSocket* socket = (QTcpSocket*)sender(); + socket->deleteLater(); +} diff --git a/plugins/feature/skymap/webserver.h b/plugins/feature/skymap/webserver.h new file mode 100644 index 000000000..da3e034b3 --- /dev/null +++ b/plugins/feature/skymap/webserver.h @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022-2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_WEB_SERVER_H_ +#define INCLUDE_WEB_SERVER_H_ + +#include +#include + +// WebServer for making simple dynamic html pages and serving binaries from +// resources or local disk +class WebServer : public QTcpServer +{ + Q_OBJECT + + struct Substitution { + QString m_from; + QString m_to; + Substitution(const QString& from, const QString& to) : + m_from(from), + m_to(to) + { + } + }; + + struct MimeType { + QString m_type; + bool m_binary; + MimeType(const QString& type, bool binary=true) : + m_type(type), + m_binary(binary) + { + } + }; + +private: + + // Hash of a list of paths to substitute + QHash m_pathSubstitutions; + + // Hash of path to a list of substitutions to make in the file + QHash*> m_substitutions; + + // Hash of files held in memory + QHash m_files; + + // Hash of filename extension to MIME type information + QHash m_mimeTypes; + MimeType m_defaultMimeType; + +public: + WebServer(quint16 &port, QObject* parent = 0); + void incomingConnection(qintptr socket) override; + void addPathSubstitution(const QString &from, const QString &to); + void addSubstitution(QString path, QString from, QString to); + void addFile(const QString &path, const QByteArray &data); + QString substitute(QString path, QString html); + void sendFile(QTcpSocket* socket, const QByteArray &data, MimeType *mimeType, const QString &path); + +private slots: + void readClient(); + void discardClient(); + +}; + +#endif diff --git a/plugins/feature/skymap/websocketserver.cpp b/plugins/feature/skymap/websocketserver.cpp new file mode 100644 index 000000000..9d59886f3 --- /dev/null +++ b/plugins/feature/skymap/websocketserver.cpp @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "websocketserver.h" + +WebSocketServer::WebSocketServer(QObject *parent) : + QObject(parent), + m_socket("", QWebSocketServer::NonSecureMode, this), + m_client(nullptr) +{ + connect(&m_socket, &QWebSocketServer::newConnection, this, &WebSocketServer::onNewConnection); + int port = 0; + if (!m_socket.listen(QHostAddress::Any, port)) { + qCritical() << "WebSocketServer - Unable to listen on port " << port; + } +} + +quint16 WebSocketServer::serverPort() +{ + return m_socket.serverPort(); +} + +void WebSocketServer::onNewConnection() +{ + QWebSocket *socket = m_socket.nextPendingConnection(); + + connect(socket, &QWebSocket::textMessageReceived, this, &WebSocketServer::processTextMessage); + connect(socket, &QWebSocket::binaryMessageReceived, this, &WebSocketServer::processBinaryMessage); + connect(socket, &QWebSocket::disconnected, this, &WebSocketServer::socketDisconnected); + + m_client = socket; + + emit connected(); +} + +void WebSocketServer::processTextMessage(QString message) +{ + //QWebSocket *client = qobject_cast(sender()); + //qDebug() << "WebSocketServer::processTextMessage - Received text " << message; + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error); + if (!doc.isNull() && doc.isObject()) { + emit received(doc.object()); + } else { + qDebug() << "WebSocketServer::processTextMessage: " << error.errorString(); + } +} + +void WebSocketServer::processBinaryMessage(QByteArray message) +{ + //QWebSocket *client = qobject_cast(sender()); + // Shouldn't receive any binary messages for now + qDebug() << "WebSocketServer::processBinaryMessage - Received binary " << message; +} + +void WebSocketServer::socketDisconnected() +{ + QWebSocket *client = qobject_cast(sender()); + if (client) { + client->deleteLater(); + m_client = nullptr; + } +} + +bool WebSocketServer::isConnected() +{ + return m_client != nullptr; +} + +void WebSocketServer::send(const QJsonObject &obj) +{ + if (m_client) + { + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + qint64 bytesSent = m_client->sendTextMessage(bytes); + m_client->flush(); // Try to reduce latency + if (bytesSent != bytes.size()) { + qDebug() << "WebSocketServer::update - Sent only " << bytesSent << " bytes out of " << bytes.size(); + } + //qDebug() << obj; + } +} + diff --git a/plugins/feature/skymap/websocketserver.h b/plugins/feature/skymap/websocketserver.h new file mode 100644 index 000000000..26d4a1510 --- /dev/null +++ b/plugins/feature/skymap/websocketserver.h @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// Copyright (C) 2015-2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021-2022 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_WEBSOCKERSERVER_H_ +#define INCLUDE_FEATURE_WEBSOCKERSERVER_H_ + +#include +#include +#include +#include + +class WebSocketServer : public QObject +{ + Q_OBJECT + +private: + + QWebSocketServer m_socket; + QWebSocket *m_client; + +public: + + WebSocketServer(QObject *parent = nullptr); + quint16 serverPort(); + + bool isConnected(); + void send(const QJsonObject &obj); + +signals: + void connected(); + void received(const QJsonObject &obj); + +public slots: + + void onNewConnection(); + void processTextMessage(QString message); + void processBinaryMessage(QByteArray message); + void socketDisconnected(); + +}; + +#endif // INCLUDE_FEATURE_MAPWEBSOCKERSERVER_H_ diff --git a/plugins/feature/skymap/webview.cpp b/plugins/feature/skymap/webview.cpp new file mode 100644 index 000000000..7d424cc34 --- /dev/null +++ b/plugins/feature/skymap/webview.cpp @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "webview.h" + +#include +#include +#include + +WebView::WebView(QWidget *parent) : + QWebEngineView(parent) +{ +} + +QWebEngineView *WebView::createWindow(QWebEnginePage::WebWindowType type) +{ + (void) type; + QWebEngineView *view = new QWebEngineView(); + connect(view, &QWebEngineView::titleChanged, this, &WebView::on_titleChanged); + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(view); + + int tab = m_tabs->addTab(view, "Web"); + m_tabs->setCurrentIndex(tab); + + return view; +} + +void WebView::on_titleChanged(const QString& title) +{ + QWebEngineView *view = qobject_cast(sender()); + for (int i = 0; i < m_tabs->count(); i++) + { + if (m_tabs->widget(i) == view) { + m_tabs->setTabText(i, title); + } + } +} diff --git a/plugins/feature/skymap/webview.h b/plugins/feature/skymap/webview.h new file mode 100644 index 000000000..d0ed1a157 --- /dev/null +++ b/plugins/feature/skymap/webview.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FEATURE_WEBVIEW_H_ +#define INCLUDE_FEATURE_WEBVIEW_H_ + +#include + +#include "websocketserver.h" + +class QTabWidget; + +class WebView : public QWebEngineView +{ + Q_OBJECT + +public: + + WebView(QWidget *parent = nullptr); + + QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override; + + void setTabs(QTabWidget *tabs) { m_tabs = tabs; } + +private slots: + void on_titleChanged(const QString& title); + +private: + QTabWidget *m_tabs; +}; + +#endif // INCLUDE_FEATURE_WEBVIEW_H_ diff --git a/plugins/feature/skymap/wtml.cpp b/plugins/feature/skymap/wtml.cpp new file mode 100644 index 000000000..c7210e2bb --- /dev/null +++ b/plugins/feature/skymap/wtml.cpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "wtml.h" + +#include +#include +#include +#include + +WTML::WTML() +{ + m_networkManager = new QNetworkAccessManager(); + QObject::connect(m_networkManager, &QNetworkAccessManager::finished, this, &WTML::handleReply); +} + +WTML::~WTML() +{ + QObject::disconnect(m_networkManager, &QNetworkAccessManager::finished, this, &WTML::handleReply); + delete m_networkManager; +} + +void WTML::getData() +{ + // https://worldwidetelescope.org/wwtweb/catalog.aspx?X=ImageSets6 + // https://worldwidetelescope.org/wwtweb/catalog.aspx?W=exploreroot6 + QUrl url(QString("https://worldwidetelescope.org/wwtweb/catalog.aspx?X=ImageSets6")); + m_networkManager->get(QNetworkRequest(url)); +} + +void WTML::handleReply(QNetworkReply* reply) +{ + if (!reply->error()) + { + QXmlStreamReader xmlReader(reply->readAll()); + + QList dataSets; + + while (!xmlReader.atEnd() && !xmlReader.hasError()) + { + while (xmlReader.readNextStartElement()) + { + if (xmlReader.name() == QLatin1String("Folder")) + { + while(xmlReader.readNextStartElement()) + { + if (xmlReader.name() == QLatin1String("ImageSet")) + { + QString name = xmlReader.attributes().value("Name").toString(); + QString dataSetType = xmlReader.attributes().value("DataSetType").toString(); + + if (!name.isEmpty() && !dataSetType.isEmpty()) + { + ImageSet imageSet; + imageSet.m_name = name; + imageSet.m_dataSetType = dataSetType; + dataSets.append(imageSet); + //qDebug() << "Adding ImageSet " << name << dataSetType; + } + + // Credits, Thumbnail etc + while(xmlReader.readNextStartElement()) + { + xmlReader.skipCurrentElement(); + } + } + else + { + xmlReader.skipCurrentElement(); + } + } + } + else + { + xmlReader.skipCurrentElement(); + } + } + } + // Ignore "Premature end of document." here even if ok + if (!xmlReader.atEnd() && xmlReader.hasError()) { + qDebug() << "WTML::handleReply: Error parsing XML: " << xmlReader.errorString(); + } + + emit dataUpdated(dataSets); + } + else + { + qDebug() << "WTML::handleReply: error: " << reply->error(); + } + reply->deleteLater(); +} diff --git a/plugins/feature/skymap/wtml.h b/plugins/feature/skymap/wtml.h new file mode 100644 index 000000000..6e3db15fb --- /dev/null +++ b/plugins/feature/skymap/wtml.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_WTML_H +#define INCLUDE_WTML_H + +#include + +class QNetworkAccessManager; +class QNetworkReply; + +// World Wide Telescope WTML files containing imageset catalogs +class WTML : public QObject +{ + Q_OBJECT + +public: + + struct ImageSet { + QString m_name; + QString m_dataSetType; + }; + + WTML(); + ~WTML(); + + void getData(); + +public slots: + void handleReply(QNetworkReply* reply); + +signals: + void dataUpdated(const QList& dataSets); // Emitted when new data are available. + +private: + QNetworkAccessManager *m_networkManager; + +}; + +#endif /* INCLUDE_WTML_H */ diff --git a/plugins/feature/startracker/readme.md b/plugins/feature/startracker/readme.md index 39ab6f720..d2cbf6311 100644 --- a/plugins/feature/startracker/readme.md +++ b/plugins/feature/startracker/readme.md @@ -9,6 +9,7 @@ The Star Tracker feature plugin is for use in radio astronomy and EME (Earth-Moo * The overhead position of the Sun, Moon and selected star can be displayed on the Map Feature. * It can display local Sidereal time, solar flux density and sky temperature. * It can plot the line of sight through the Milky Way. +* It can send the target to the Sky Map plugin, to display associated imagery in a variety of wavelengths. It can also use the Sky Map to set the target. * The plugin can communicate with Stellarium, allowing Stellarium to control SDRangel as though it was a telescope and for the direction the antenna is pointing to be displayed in Stellarium.

Settings

@@ -66,7 +67,7 @@ Specifies the longitude in decimal degrees (East positive) of the observation po

8: Time

-Select the date and time at which the position of the target should be calculated. Select either Now, for the current time, or Custom to manually enter a date and time. +Select the local date and time at which the position of the target should be calculated. Select either Now, for the current time, or Custom to manually enter a date and time.

9: LST - Local Sidereal Time

@@ -100,6 +101,7 @@ To allow Stellarium to set the RA and Dec, select Custom RA/Dec, and ensure the | S8 | HI | IAU primary calibration region (l=207,b=-15) | Tb=72 peak | | S9 | HI | IAU secondary calibration region (l=356,b=-4) | Tb=85 peak | | SatelliteTracker | | Gets target Az/El from Satellite Tracker | | +| SkyMap | | Gets target RA/Dec from Sky Map Tracker | | References: @@ -240,6 +242,12 @@ The Star Tracker feature can send the overhead position of the Sun, Moon and tar When using the Find feature in the Map GUI, you can search for "Sun", "Moon" or "Star". +

Sky Map

+ +The Star Tracker feature will send the target RA/Dec, observation point (antenna location) and antenna beamwidth to the Sky Map. +If the Star Tracker is set as the Source plugin in the Sky Map, pressing the Track button in the Sky Map will result in the Sky Map tracking the target +selected in the Star Tracker. +

Stellarium Interface

In Star Tracker: @@ -288,15 +296,15 @@ Icons are by Freepik from Flaticon https://www.flaticon.com/ Full details of the API can be found in the Swagger documentation. Here is a quick example of how to set the target to the Moon at the current time: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "StarTracker", "StarTrackerSettings": { "target": "Moon", "dateTime": "" }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "StarTracker", "StarTrackerSettings": { "target": "Moon", "dateTime": "" }}' Or to a custom RA and declination on a given date and time: - curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "StarTracker", "StarTrackerSettings": { "target": "Custom", "ra": "03h32m59.35s", "dec": "54d34m45.05s", "dateTime": "1921-04-15T10:17:05" }}' + curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/feature/0/settings" -d '{"featureType": "StarTracker", "StarTrackerSettings": { "target": "Custom", "ra": "03h32m59.35s", "dec": "54d34m45.05s", "dateTime": "1921-04-15T10:17:05" }}' To start tracking: - curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/run" + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/feature/0/run"

Developer Notes

diff --git a/plugins/feature/startracker/startracker.cpp b/plugins/feature/startracker/startracker.cpp index 9f8572ee8..fdd9846d6 100644 --- a/plugins/feature/startracker/startracker.cpp +++ b/plugins/feature/startracker/startracker.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -42,7 +42,8 @@ MESSAGE_CLASS_DEFINITION(StarTracker::MsgConfigureStarTracker, Message) MESSAGE_CLASS_DEFINITION(StarTracker::MsgStartStop, Message) MESSAGE_CLASS_DEFINITION(StarTracker::MsgSetSolarFlux, Message) -MESSAGE_CLASS_DEFINITION(StarTracker::MsgReportAvailableSatelliteTrackers, Message) +MESSAGE_CLASS_DEFINITION(StarTracker::MsgRequestAvailableFeatures, Message) +MESSAGE_CLASS_DEFINITION(StarTracker::MsgReportAvailableFeatures, Message) const char* const StarTracker::m_featureIdURI = "sdrangel.feature.startracker"; const char* const StarTracker::m_featureId = "StarTracker"; @@ -50,7 +51,9 @@ const char* const StarTracker::m_featureId = "StarTracker"; StarTracker::StarTracker(WebAPIAdapterInterface *webAPIAdapterInterface) : Feature(m_featureIdURI, webAPIAdapterInterface), m_thread(nullptr), - m_worker(nullptr) + m_worker(nullptr), + m_availableChannelHandler({"sdrangel.channel.radioastronomy"}, QStringList{"startracker.display"}), + m_availableFeatureHandler({"sdrangel.feature.satellitetracker", "sdrangel.feature.skymap"}) { qDebug("StarTracker::StarTracker: webAPIAdapterInterface: %p", webAPIAdapterInterface); setObjectName(m_featureId); @@ -70,36 +73,17 @@ StarTracker::StarTracker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_temps.append(new FITS(":/startracker/startracker/408mhz_ra_dec.fits")); m_temps.append(new FITS(":/startracker/startracker/1420mhz_ra_dec.fits")); m_spectralIndex = new FITS(":/startracker/startracker/408mhz_ra_dec_spectral_index.fits"); - scanAvailableChannels(); - scanAvailableFeatures(); - QObject::connect( - MainCore::instance(), - &MainCore::channelAdded, - this, - &StarTracker::handleChannelAdded - ); - QObject::connect( - MainCore::instance(), - &MainCore::featureAdded, - this, - &StarTracker::handleFeatureAdded - ); - QObject::connect( - MainCore::instance(), - &MainCore::featureRemoved, - this, - &StarTracker::handleFeatureRemoved - ); + + QObject::connect(&m_availableChannelHandler, &AvailableChannelOrFeatureHandler::messageEnqueued, this, &StarTracker::handleChannelMessageQueue); + m_availableChannelHandler.scanAvailableChannelsAndFeatures(); + QObject::connect(&m_availableFeatureHandler, &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, &StarTracker::featuresChanged); + m_availableFeatureHandler.scanAvailableChannelsAndFeatures(); } StarTracker::~StarTracker() { - QObject::disconnect( - MainCore::instance(), - &MainCore::channelAdded, - this, - &StarTracker::handleChannelAdded - ); + QObject::disconnect(&m_availableChannelHandler, &AvailableChannelOrFeatureHandler::messageEnqueued, this, &StarTracker::handleChannelMessageQueue); + QObject::disconnect(&m_availableFeatureHandler, &AvailableChannelOrFeatureHandler::channelsOrFeaturesChanged, this, &StarTracker::featuresChanged); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -176,6 +160,11 @@ bool StarTracker::handleMessage(const Message& cmd) return true; } + else if (MsgRequestAvailableFeatures::match(cmd)) + { + notifyUpdateFeatures(); + return true; + } else if (MsgSetSolarFlux::match(cmd)) { MsgSetSolarFlux& msg = (MsgSetSolarFlux&) cmd; @@ -839,137 +828,18 @@ bool StarTracker::calcSkyTemperature(double frequency, double beamwidth, double } } -void StarTracker::scanAvailableChannels() +void StarTracker::featuresChanged() { - MainCore *mainCore = MainCore::instance(); - MessagePipes& messagePipes = mainCore->getMessagePipes(); - std::vector& deviceSets = mainCore->getDeviceSets(); - m_availableChannels.clear(); - - for (const auto& deviceSet : deviceSets) - { - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine) - { - for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) - { - ChannelAPI *channel = deviceSet->getChannelAt(chi); - - if (StarTrackerSettings::m_pipeURIs.contains(channel->getURI()) && !m_availableChannels.contains(channel)) - { - qDebug("StarTracker::scanAvailableChannels: register %d:%d %s (%p)", - deviceSet->getIndex(), chi, qPrintable(channel->getURI()), channel); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "startracker.display"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &StarTracker::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } - } - } + m_availableFeatures = m_availableFeatureHandler.getAvailableChannelOrFeatureList(); + notifyUpdateFeatures(); } -void StarTracker::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) -{ - qDebug("StarTracker::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", - deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); - DeviceSet *deviceSet = MainCore::instance()->getDeviceSets()[deviceSetIndex]; - DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; - - if (deviceSourceEngine && StarTrackerSettings::m_pipeURIs.contains(channel->getURI())) - { - if (!m_availableChannels.contains(channel)) - { - MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channel, this, "startracker.display"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleChannelMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - QObject::connect( - pipe, - &ObjectPipe::toBeDeleted, - this, - &StarTracker::handleMessagePipeToBeDeleted - ); - m_availableChannels.insert(channel); - } - } -} - -void StarTracker::handleMessagePipeToBeDeleted(int reason, QObject* object) -{ - if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) - { - qDebug("StarTracker::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } -} - -void StarTracker::scanAvailableFeatures() -{ - qDebug("StarTracker::scanAvailableFeatures"); - MainCore *mainCore = MainCore::instance(); - std::vector& featureSets = mainCore->getFeatureeSets(); - m_satelliteTrackers.clear(); - - for (const auto& featureSet : featureSets) - { - for (int fei = 0; fei < featureSet->getNumberOfFeatures(); fei++) - { - Feature *feature = featureSet->getFeatureAt(fei); - - if (feature->getURI() == "sdrangel.feature.satellitetracker") - { - StarTrackerSettings::AvailableFeature satelliteTracker = - StarTrackerSettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; - m_satelliteTrackers[feature] = satelliteTracker; - } - } - } - - notifyUpdateSatelliteTrackers(); -} - -void StarTracker::handleFeatureAdded(int featureSetIndex, Feature *feature) -{ - (void) featureSetIndex; - (void) feature; - - scanAvailableFeatures(); -} - -void StarTracker::handleFeatureRemoved(int featureSetIndex, Feature *feature) -{ - (void) featureSetIndex; - (void) feature; - - scanAvailableFeatures(); -} - -void StarTracker::notifyUpdateSatelliteTrackers() +void StarTracker::notifyUpdateFeatures() { if (getMessageQueueToGUI()) { - MsgReportAvailableSatelliteTrackers *msg = MsgReportAvailableSatelliteTrackers::create(); - msg->getFeatures() = m_satelliteTrackers.values(); + MsgReportAvailableFeatures *msg = MsgReportAvailableFeatures::create(); + msg->getFeatures() = m_availableFeatures; getMessageQueueToGUI()->push(msg); } } diff --git a/plugins/feature/startracker/startracker.h b/plugins/feature/startracker/startracker.h index 99d44e891..c72e7e572 100644 --- a/plugins/feature/startracker/startracker.h +++ b/plugins/feature/startracker/startracker.h @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2020-2022 Edouard Griffiths, F4EXB // // Copyright (C) 2020 Kacper Michajłow // -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 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 // @@ -22,11 +22,11 @@ #include #include -#include #include "feature/feature.h" #include "util/message.h" #include "util/fits.h" +#include "availablechannelorfeaturehandler.h" #include "startrackersettings.h" @@ -107,20 +107,34 @@ public: { } }; - class MsgReportAvailableSatelliteTrackers : public Message { + class MsgRequestAvailableFeatures : public Message { MESSAGE_CLASS_DECLARATION public: - QList& getFeatures() { return m_availableFeatures; } - - static MsgReportAvailableSatelliteTrackers* create() { - return new MsgReportAvailableSatelliteTrackers(); + static MsgRequestAvailableFeatures* create() { + return new MsgRequestAvailableFeatures(); } private: - QList m_availableFeatures; + MsgRequestAvailableFeatures() : + Message() + {} + }; - MsgReportAvailableSatelliteTrackers() : + class MsgReportAvailableFeatures : public Message { + MESSAGE_CLASS_DECLARATION + + public: + AvailableChannelOrFeatureList& getFeatures() { return m_availableFeatures; } + + static MsgReportAvailableFeatures* create() { + return new MsgReportAvailableFeatures(); + } + + private: + AvailableChannelOrFeatureList m_availableFeatures; + + MsgReportAvailableFeatures() : Message() {} }; @@ -183,11 +197,13 @@ private: QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; - QSet m_availableChannels; - QHash m_satelliteTrackers; Weather *m_weather; float m_solarFlux; + AvailableChannelOrFeatureHandler m_availableChannelHandler; + AvailableChannelOrFeatureHandler m_availableFeatureHandler; + AvailableChannelOrFeatureList m_availableFeatures; + QList m_temps; FITS *m_spectralIndex; @@ -197,17 +213,12 @@ private: void webapiReverseSendSettings(const QList& featureSettingsKeys, const StarTrackerSettings& settings, bool force); void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); double applyBeam(const FITS *fits, double beamwidth, double ra, double dec, int& imgX, int& imgY) const; - void scanAvailableChannels(); - void scanAvailableFeatures(); - void notifyUpdateSatelliteTrackers(); + void notifyUpdateFeatures(); private slots: void networkManagerFinished(QNetworkReply *reply); void weatherUpdated(float temperature, float pressure, float humidity); - void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); - void handleMessagePipeToBeDeleted(int reason, QObject* object); - void handleFeatureAdded(int featureSetIndex, Feature *feature); - void handleFeatureRemoved(int featureSetIndex, Feature *feature); + void featuresChanged(); void handleChannelMessageQueue(MessageQueue* messageQueue); }; diff --git a/plugins/feature/startracker/startrackergui.cpp b/plugins/feature/startracker/startrackergui.cpp index 2fe36a244..367a6ba4a 100644 --- a/plugins/feature/startracker/startrackergui.cpp +++ b/plugins/feature/startracker/startrackergui.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2021-2023 Jon Beniston, M7RCE // +// Copyright (C) 2021-2024 Jon Beniston, M7RCE // // Copyright (C) 2021-2022 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // @@ -220,31 +220,31 @@ bool StarTrackerGUI::handleMessage(const Message& message) } return true; } - else if (StarTracker::MsgReportAvailableSatelliteTrackers::match(message)) + else if (StarTracker::MsgReportAvailableFeatures::match(message)) { - StarTracker::MsgReportAvailableSatelliteTrackers& report = (StarTracker::MsgReportAvailableSatelliteTrackers&) message; - updateSatelliteTrackerList(report.getFeatures()); + StarTracker::MsgReportAvailableFeatures& report = (StarTracker::MsgReportAvailableFeatures&) message; + updateFeatureList(report.getFeatures()); return true; } return false; } -void StarTrackerGUI::updateSatelliteTrackerList(const QList& satelliteTrackers) +void StarTrackerGUI::updateFeatureList(const AvailableChannelOrFeatureList& features) { - // Update list of satellite trackers + // Update list of plugins we can get target from ui->target->blockSignals(true); - // Remove Satellite Trackers no longer available + // Remove targets no longer available for (int i = 0; i < ui->target->count(); ) { QString text = ui->target->itemText(i); bool found = false; - if (text.contains("SatelliteTracker")) + if (text.contains("SatelliteTracker") || text.contains("SkyMap")) { - for (const auto& satelliteTracker : satelliteTrackers) + for (const auto& feature : features) { - if (satelliteTracker.getName() == text) + if (feature.getLongId() == text) { found = true; break; @@ -262,16 +262,16 @@ void StarTrackerGUI::updateSatelliteTrackerList(const QListtarget->findText(name) == -1) { ui->target->addItem(name); } } - // Satellite Tracker feature can be created after this plugin, so select it + // Features can be created after this plugin, so select it // if the chosen tracker appears int index = ui->target->findText(m_settings.m_target); if (index >= 0) { @@ -454,6 +454,9 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, createGalacticLineOfSightScene(); plotChart(); + + StarTracker::MsgRequestAvailableFeatures *message = StarTracker::MsgRequestAvailableFeatures::create(); + m_starTracker->getInputMessageQueue()->push(message); } StarTrackerGUI::~StarTrackerGUI() diff --git a/plugins/feature/startracker/startrackergui.h b/plugins/feature/startracker/startrackergui.h index 0728fcdaf..d607f603a 100644 --- a/plugins/feature/startracker/startrackergui.h +++ b/plugins/feature/startracker/startrackergui.h @@ -33,6 +33,7 @@ #include "util/fits.h" #include "gui/httpdownloadmanagergui.h" #include "settings/rollupstate.h" +#include "availablechannelorfeature.h" #include "startrackersettings.h" @@ -169,7 +170,7 @@ private: void updateSolarFlux(bool all); void makeUIConnections(); void limitAzElRange(double& azimuth, double& elevation) const; - void updateSatelliteTrackerList(const QList& satelliteTrackers); + void updateFeatureList(const AvailableChannelOrFeatureList& features); private slots: void onMenuDialogCalled(const QPoint &p); diff --git a/plugins/feature/startracker/startrackergui.ui b/plugins/feature/startracker/startrackergui.ui index bc41ef77b..933b27733 100644 --- a/plugins/feature/startracker/startrackergui.ui +++ b/plugins/feature/startracker/startrackergui.ui @@ -141,10 +141,10 @@ Antenna half power (-3dB) beamwidth (degrees) - 1 + 2 - 0.100000000000000 + 0.010000000000000 360.000000000000000 diff --git a/plugins/feature/startracker/startrackersettings.cpp b/plugins/feature/startracker/startrackersettings.cpp index b438a84e1..98c7c38b5 100644 --- a/plugins/feature/startracker/startrackersettings.cpp +++ b/plugins/feature/startracker/startrackersettings.cpp @@ -23,14 +23,6 @@ #include "startrackersettings.h" -const QStringList StarTrackerSettings::m_pipeTypes = { - QStringLiteral("RadioAstronomy") -}; - -const QStringList StarTrackerSettings::m_pipeURIs = { - QStringLiteral("sdrangel.channel.radioastronomy") -}; - StarTrackerSettings::StarTrackerSettings() : m_rollupState(nullptr) { diff --git a/plugins/feature/startracker/startrackersettings.h b/plugins/feature/startracker/startrackersettings.h index b4de84bd0..1bd2afa55 100644 --- a/plugins/feature/startracker/startrackersettings.h +++ b/plugins/feature/startracker/startrackersettings.h @@ -2,7 +2,7 @@ // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // // written by Christian Daniel // // Copyright (C) 2015-2022 Edouard Griffiths, F4EXB // -// Copyright (C) 2020-2021, 2023 Jon Beniston, M7RCE // +// Copyright (C) 2020-2024 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 // @@ -30,29 +30,12 @@ class Serializable; struct StarTrackerSettings { - struct AvailableFeature - { - int m_featureSetIndex; - int m_featureIndex; - QString m_type; - - AvailableFeature() = default; - AvailableFeature(const AvailableFeature&) = default; - AvailableFeature& operator=(const AvailableFeature&) = default; - bool operator==(const AvailableFeature& a) const { - return (m_featureSetIndex == a.m_featureSetIndex) && (m_featureIndex == a.m_featureIndex) && (m_type == a.m_type); - } - QString getName() const { - return QString("F%1:%2 %3").arg(m_featureSetIndex).arg(m_featureIndex).arg(m_type); - } - }; - QString m_ra; QString m_dec; double m_latitude; double m_longitude; QString m_target; // Sun, Moon, Custom - QString m_dateTime; // Date/time for observation, or "" for now + QString m_dateTime; // Local date/time for observation, or "" for now QString m_refraction; // Refraction correction. "None", "Saemundsson" or "Positional Astronomy Library" double m_pressure; // Air pressure in millibars double m_temperature; // Air temperature in C @@ -102,9 +85,6 @@ struct StarTrackerSettings void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } void applySettings(const QStringList& settingsKeys, const StarTrackerSettings& settings); QString getDebugString(const QStringList& settingsKeys, bool force=false) const; - - static const QStringList m_pipeTypes; - static const QStringList m_pipeURIs; }; #endif // INCLUDE_FEATURE_STARTRACKERSETTINGS_H_ diff --git a/plugins/feature/startracker/startrackerworker.cpp b/plugins/feature/startracker/startrackerworker.cpp index 81516b39e..cd62c0bab 100644 --- a/plugins/feature/startracker/startrackerworker.cpp +++ b/plugins/feature/startracker/startrackerworker.cpp @@ -30,6 +30,7 @@ #include "SWGTargetAzimuthElevation.h" #include "SWGMapItem.h" #include "SWGStarTrackerTarget.h" +#include "SWGSkyMapTarget.h" #include "webapi/webapiadapterinterface.h" #include "webapi/webapiutils.h" @@ -384,7 +385,7 @@ void StarTrackerWorker::updateRaDec(RADec rd, QDateTime dt, bool lbTarget) // Send to Stellarium writeStellariumTarget(rdJ2000.ra, rdJ2000.dec); // Send to GUI - if (m_settings.m_target == "Sun" || m_settings.m_target == "Moon" || (m_settings.m_target == "Custom Az/El") || lbTarget || m_settings.m_target.contains("SatelliteTracker")) + if (m_settings.m_target == "Sun" || m_settings.m_target == "Moon" || (m_settings.m_target == "Custom Az/El") || lbTarget || m_settings.m_target.contains("SatelliteTracker") || m_settings.m_target.contains("SkyMap")) { if (getMessageQueueToGUI()) { @@ -517,6 +518,26 @@ void StarTrackerWorker::update() else qDebug() << "StarTrackerWorker::update - Failed to parse feature name " << m_settings.m_target; } + if (m_settings.m_target.contains("SkyMap")) + { + // Get RA/Dec from Sky Map + double ra, dec; + unsigned int featureSetIndex,featureIndex; + + if (MainCore::getFeatureIndexFromId(m_settings.m_target, featureSetIndex, featureIndex)) + { + if (ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "ra", ra) + && ChannelWebAPIUtils::getFeatureReportValue(featureSetIndex, featureIndex, "dec", dec)) + { + m_settings.m_ra = QString::number(ra, 'f', 10); + m_settings.m_dec = QString::number(dec, 'f', 10); + } + else + qDebug() << "StarTrackerWorker::update - Failed to target from feature " << m_settings.m_target; + } + else + qDebug() << "StarTrackerWorker::update - Failed to parse feature name " << m_settings.m_target; + } if (m_settings.m_target == "Sun") { @@ -654,6 +675,33 @@ void StarTrackerWorker::update() } } + // Send RA/Dec, position, beamwidth and date to Sky Map + QList skyMapPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(m_starTracker, "skymap.target", skyMapPipes); + for (const auto& pipe : skyMapPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGSkyMapTarget *swgTarget = new SWGSDRangel::SWGSkyMapTarget(); + if (m_settings.m_jnow) + { + double jd = Astronomy::julianDate(dt); + RADec rdJ2000 = Astronomy::precess(rd, jd, Astronomy::jd_j2000()); + swgTarget->setRa(rdJ2000.ra); + swgTarget->setDec(rdJ2000.dec); + } + else + { + swgTarget->setRa(rd.ra); + swgTarget->setDec(rd.dec); + } + swgTarget->setLatitude(m_settings.m_latitude); + swgTarget->setLongitude(m_settings.m_longitude); + swgTarget->setAltitude(m_settings.m_heightAboveSeaLevel); + swgTarget->setDateTime(new QString(dt.toString(Qt::ISODateWithMs))); + swgTarget->setHpbw(m_settings.m_beamwidth); + messageQueue->push(MainCore::MsgSkyMapTarget::create(m_starTracker, swgTarget)); + } + // Send to Map if (m_settings.m_drawSunOnMap || m_settings.m_drawMoonOnMap || m_settings.m_drawStarOnMap) { diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 923dd1da3..987eda401 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -286,6 +286,8 @@ set(sdrbase_SOURCES websockets/wsspectrum.cpp + availablechannelorfeature.cpp + availablechannelorfeaturehandler.cpp mainparser.cpp maincore.cpp remotetcpsinkstarter.cpp @@ -525,6 +527,8 @@ set(sdrbase_HEADERS websockets/wsspectrum.h + availablechannelorfeature.h + availablechannelorfeaturehandler.h mainparser.h maincore.h remotetcpsinkstarter.h diff --git a/sdrbase/availablechannelorfeature.cpp b/sdrbase/availablechannelorfeature.cpp new file mode 100644 index 000000000..1b5de904f --- /dev/null +++ b/sdrbase/availablechannelorfeature.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "availablechannelorfeature.h" +#include "feature/feature.h" +#include "channel/channelapi.h" +#include "maincore.h" + +int AvailableChannelOrFeatureList::indexOfObject(const QObject *object, int from) const +{ + for (int index = from; index < size(); index++) + { + if (at(index).m_object == object) { + return index; + } + } + return -1; +} + +int AvailableChannelOrFeatureList::indexOfId(const QString& id, int from) const +{ + for (int index = from; index < size(); index++) + { + if (at(index).getId() == id) { + return index; + } + } + return -1; +} + +int AvailableChannelOrFeatureList::indexOfLongId(const QString& longId, int from) const +{ + for (int index = from; index < size(); index++) + { + if (at(index).getLongId() == longId) { + return index; + } + } + return -1; +} diff --git a/sdrbase/availablechannelorfeature.h b/sdrbase/availablechannelorfeature.h new file mode 100644 index 000000000..5c152c2d0 --- /dev/null +++ b/sdrbase/availablechannelorfeature.h @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_AVAILABLECHANNELORFEATURE_H_ +#define SDRBASE_AVAILABLECHANNELORFEATURE_H_ + +#include "pipes/messagepipes.h" +#include "export.h" + +struct AvailableChannelOrFeature +{ + QChar m_kind; //!< 'R' or 'T' for channel, 'M' for MIMO channel, 'F' for feature as from MainCore::getDeviceSetTypeId + int m_superIndex; //!< Device Set index or Feature Set index + int m_index; //!< Channel or Feature index + int m_streamIndex; //!< For MIMO channels only + QString m_type; //!< Plugin type (E.g. NFMDemod) + QObject *m_object; //!< Pointer to the object (ChannelAPI or Feature object) + + AvailableChannelOrFeature() = default; + AvailableChannelOrFeature(const AvailableChannelOrFeature&) = default; + AvailableChannelOrFeature& operator=(const AvailableChannelOrFeature&) = default; + + bool operator==(const AvailableChannelOrFeature& a) const { + return (m_kind == a.m_kind) && (m_superIndex == a.m_superIndex) && (m_index == a.m_index) && (m_type == a.m_type) && ((m_kind == 'M') && (m_streamIndex == a.m_streamIndex)); + } + + QString getId() const { // Eg: "R3:4" + QString id = QString("%1%2:%3").arg(m_kind).arg(m_superIndex).arg(m_index); + if (m_kind == 'M') { + id.append(QString(".%1").arg(m_streamIndex)); + } + return id; + } + + QString getLongId() const { // Eg: "F0:1 StarTracker" + return QString("%1 %2").arg(getId()).arg(m_type); + } +}; + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +inline uint qHash(const AvailableChannelOrFeature &c, uint seed = 0) noexcept +{ + return qHash(c.getLongId(), seed); +} +#else +inline size_t qHash(const AvailableChannelOrFeature &c, size_t seed = 0) noexcept +{ + return qHash(c.getLongId(), seed); +} +#endif + +class SDRBASE_API AvailableChannelOrFeatureList : public QList +{ +public: + AvailableChannelOrFeatureList() {} + inline explicit AvailableChannelOrFeatureList(const AvailableChannelOrFeature &i) { append(i); } + + int indexOfObject(const QObject *object, int from=0) const; //!< // Find index of entry containing specified object. -1 if not found. + int indexOfId(const QString& longId, int from=0) const; //!< // Find index of entry with specified Id. -1 if not found. + int indexOfLongId(const QString& longId, int from=0) const; //!< // Find index of entry with specified long Id. -1 if not found. +}; + +#endif // SDRBASE_AVAILABLECHANNELORFEATURE_H_ diff --git a/sdrbase/availablechannelorfeaturehandler.cpp b/sdrbase/availablechannelorfeaturehandler.cpp new file mode 100644 index 000000000..eb08af7ff --- /dev/null +++ b/sdrbase/availablechannelorfeaturehandler.cpp @@ -0,0 +1,175 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "availablechannelorfeaturehandler.h" +#include "feature/feature.h" +#include "channel/channelapi.h" +#include "maincore.h" + +void AvailableChannelOrFeatureHandler::init() +{ + QObject::connect(MainCore::instance(), &MainCore::channelAdded, this, &AvailableChannelOrFeatureHandler::handleChannelAdded); + QObject::connect(MainCore::instance(), &MainCore::channelRemoved, this, &AvailableChannelOrFeatureHandler::handleChannelRemoved); + QObject::connect(MainCore::instance(), &MainCore::featureAdded, this, &AvailableChannelOrFeatureHandler::handleFeatureAdded); + QObject::connect(MainCore::instance(), &MainCore::featureRemoved, this, &AvailableChannelOrFeatureHandler::handleFeatureRemoved); + // Don't call scanAvailableChannelsAndFeatures() here, as channelsOrFeaturesChanged slot will not yet be connected + // Owner should call scanAvailableChannelsAndFeatures after connection +} + +void AvailableChannelOrFeatureHandler::scanAvailableChannelsAndFeatures() +{ + // Get current list of channels and features with specified URIs + AvailableChannelOrFeatureList availableChannelOrFeatureList = MainCore::instance()->getAvailableChannelsAndFeatures(m_uris, m_kinds); + + // Look for new channels or features + for (const auto& channelOrFeature : availableChannelOrFeatureList) + { + if (!m_availableChannelOrFeatureList.contains(channelOrFeature)) + { + // For MIMO channels, get notified when stream index changes + if (channelOrFeature.m_kind == 'M') + { + ChannelAPI *channel = qobject_cast(channelOrFeature.m_object); + if (channel) { + QObject::connect(channel, &ChannelAPI::streamIndexChanged, this, &AvailableChannelOrFeatureHandler::handleStreamIndexChanged); + } + } + // Register pipes for any new channels or features + for (const auto& pipeName: m_pipeNames) { + registerPipe(pipeName, channelOrFeature.m_object); + } + } + } + + // Check to see if list has changed + bool changes = m_availableChannelOrFeatureList != availableChannelOrFeatureList; + + // Check to see if anything has been renamed, due to indexes changing after device/channel/feature removal + // or if stream index was changed + QStringList renameFrom; + QStringList renameTo; + for (const auto& channelOrFeature : availableChannelOrFeatureList) + { + int index = m_availableChannelOrFeatureList.indexOfObject(channelOrFeature.m_object); + if (index >= 0) + { + const AvailableChannelOrFeature& oldEntry = m_availableChannelOrFeatureList.at(index); + if ((oldEntry.m_superIndex != channelOrFeature.m_superIndex) + || (oldEntry.m_index != channelOrFeature.m_index) + || ((channelOrFeature.m_kind == 'M') && (oldEntry.m_streamIndex != channelOrFeature.m_streamIndex)) + ) + { + renameFrom.append(oldEntry.getId()); + renameTo.append(channelOrFeature.getId()); + renameFrom.append(oldEntry.getLongId()); + renameTo.append(channelOrFeature.getLongId()); + } + } + } + + m_availableChannelOrFeatureList = availableChannelOrFeatureList; + + // Signal if list has changed + if (changes) { + emit channelsOrFeaturesChanged(renameFrom, renameTo); + } +} + +QObject* AvailableChannelOrFeatureHandler::registerPipes(const QString& longIdFrom, const QStringList& pipeNames) +{ + int index = m_availableChannelOrFeatureList.indexOfLongId(longIdFrom); + if (index >= 0) + { + QObject *object = m_availableChannelOrFeatureList[index].m_object; + for (const auto& pipeName : pipeNames) { + registerPipe(pipeName, object); + } + return object; + } + else + { + return nullptr; + } +} + +void AvailableChannelOrFeatureHandler::deregisterPipes(QObject* from, const QStringList& pipeNames) +{ + // Don't dereference 'from' here, as it may have been deleted + if (from) + { + qDebug("AvailableChannelOrFeatureHandler::deregisterPipes: unregister (%p)", from); + MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); + for (const auto& pipeName : pipeNames) { + messagePipes.unregisterProducerToConsumer(from, this, pipeName); + } + } +} + +void AvailableChannelOrFeatureHandler::registerPipe(const QString& pipeName, QObject *channelOrFeature) +{ + qDebug("MessagePipeHandler::registerPipe: register %s (%p)", qPrintable(channelOrFeature->objectName()), channelOrFeature); + MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); + + ObjectPipe *pipe = messagePipes.registerProducerToConsumer(channelOrFeature, this, pipeName); + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + this, + [=](){ emit messageEnqueued(messageQueue); }, + Qt::QueuedConnection + ); +} + +void AvailableChannelOrFeatureHandler::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) +{ + (void) deviceSetIndex; + (void) channel; + + scanAvailableChannelsAndFeatures(); +} + +void AvailableChannelOrFeatureHandler::handleChannelRemoved(int deviceSetIndex, ChannelAPI *channel) +{ + (void) deviceSetIndex; + (void) channel; + + scanAvailableChannelsAndFeatures(); +} + +void AvailableChannelOrFeatureHandler::handleStreamIndexChanged(int streamIndex) +{ + (void) streamIndex; + + scanAvailableChannelsAndFeatures(); +} + +void AvailableChannelOrFeatureHandler::handleFeatureAdded(int featureSetIndex, Feature *feature) +{ + (void) featureSetIndex; + (void) feature; + + scanAvailableChannelsAndFeatures(); +} + +void AvailableChannelOrFeatureHandler::handleFeatureRemoved(int featureSetIndex, Feature *feature) +{ + (void) featureSetIndex; + (void) feature; + + scanAvailableChannelsAndFeatures(); +} diff --git a/sdrbase/availablechannelorfeaturehandler.h b/sdrbase/availablechannelorfeaturehandler.h new file mode 100644 index 000000000..6c94c7c50 --- /dev/null +++ b/sdrbase/availablechannelorfeaturehandler.h @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_AVAILABLECHANNELORFEATUREHANDLER_H_ +#define SDRBASE_AVAILABLECHANNELORFEATUREHANDLER_H_ + +#include "pipes/messagepipes.h" +#include "availablechannelorfeature.h" +#include "export.h" + +class ChannelAPI; +class Feature; + +// Utility class to help keeping track of list of available channels or features and optionally register pipes to them +class SDRBASE_API AvailableChannelOrFeatureHandler : public QObject +{ + Q_OBJECT + +public: + + // Use this constructor to just keep track of available channels and features with specified URIs and kinds + AvailableChannelOrFeatureHandler(QStringList uris, const QString& kinds = "RTMF") : + m_uris(uris), + m_kinds(kinds) + { + init(); + } + + // Use this constructor to keep track of available channels and features with specified URIs and kinds and register pipes with the given names to them + AvailableChannelOrFeatureHandler(QStringList uris, QStringList pipeNames, const QString& kinds = "RTMF") : + m_uris(uris), + m_pipeNames(pipeNames), + m_kinds(kinds) + { + init(); + } + + void scanAvailableChannelsAndFeatures(); + + const AvailableChannelOrFeatureList& getAvailableChannelOrFeatureList() const { + return m_availableChannelOrFeatureList; + } + + QObject* registerPipes(const QString& longIdFrom, const QStringList& pipeNames); + void deregisterPipes(QObject* from, const QStringList& pipeNames); + +private: + + AvailableChannelOrFeatureList m_availableChannelOrFeatureList; + + QStringList m_uris; //!< URIs of channels/features we want to create a list for + QStringList m_pipeNames; //!< List of pipe names to register + QString m_kinds; + + void init(); + void registerPipe(const QString& pipeName, QObject *channelOrFeature); + +private slots: + + void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); + void handleChannelRemoved(int deviceSetIndex, ChannelAPI *channel); + void handleStreamIndexChanged(int streamIndex); + void handleFeatureAdded(int featureSetIndex, Feature *feature); + void handleFeatureRemoved(int featureSetIndex, Feature *feature); + +signals: + void channelsOrFeaturesChanged(const QStringList& renameFrom, const QStringList& renameTo); //!< Emitted when list of channels or features has changed + void messageEnqueued(MessageQueue *messageQueue); //!< Emitted when message enqueued to a pipe + +}; + +#endif // SDRBASE_AVAILABLECHANNELORFEATUREHANDLER_H_ diff --git a/sdrbase/maincore.cpp b/sdrbase/maincore.cpp index d1d899d34..18e1c3a8b 100644 --- a/sdrbase/maincore.cpp +++ b/sdrbase/maincore.cpp @@ -71,6 +71,7 @@ MESSAGE_CLASS_DEFINITION(MainCore::MsgTargetAzimuthElevation, Message) MESSAGE_CLASS_DEFINITION(MainCore::MsgStarTrackerTarget, Message) MESSAGE_CLASS_DEFINITION(MainCore::MsgStarTrackerDisplaySettings, Message) MESSAGE_CLASS_DEFINITION(MainCore::MsgStarTrackerDisplayLoSSettings, Message) +MESSAGE_CLASS_DEFINITION(MainCore::MsgSkyMapTarget, Message) MainCore::MainCore() { @@ -435,6 +436,80 @@ void MainCore::updateWakeLock() } #endif +AvailableChannelOrFeatureList MainCore::getAvailableChannels(const QStringList& uris) +{ + AvailableChannelOrFeatureList list; + + for (const auto deviceSet : m_deviceSets) + { + for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) + { + ChannelAPI* channel = deviceSet->getChannelAt(chi); + + if ((uris.size() == 0) || uris.contains(channel->getURI())) + { + QChar type = getDeviceSetTypeId(deviceSet); + int streamIdx = type == 'M' ? channel->getStreamIndex() : -1; + + AvailableChannelOrFeature item { + type, + deviceSet->getIndex(), + chi, + streamIdx, + channel->getIdentifier(), + channel + }; + list.append(item); + } + } + } + + return list; +} + +AvailableChannelOrFeatureList MainCore::getAvailableFeatures(const QStringList& uris) +{ + AvailableChannelOrFeatureList list; + std::vector& featureSets = MainCore::instance()->getFeatureeSets(); + + for (const auto& featureSet : featureSets) + { + for (int fei = 0; fei < featureSet->getNumberOfFeatures(); fei++) + { + Feature *feature = featureSet->getFeatureAt(fei); + + if ((uris.size() == 0) || uris.contains(feature->getURI())) + { + AvailableChannelOrFeature item { + 'F', + featureSet->getIndex(), + fei, + -1, + feature->getIdentifier(), + feature + }; + list.append(item); + } + } + } + + return list; +} + +AvailableChannelOrFeatureList MainCore::getAvailableChannelsAndFeatures(const QStringList& uris, const QString& kinds) +{ + AvailableChannelOrFeatureList list; + + if (kinds != "F") { + list.append(getAvailableChannels(uris)); + } + if (kinds.contains("F")) { + list.append(getAvailableFeatures(uris)); + } + + return list; +} + QChar MainCore::getDeviceSetTypeId(const DeviceSet* deviceSet) { if (deviceSet->m_deviceMIMOEngine) { @@ -461,9 +536,11 @@ QString MainCore::getChannelId(const ChannelAPI* channel) DeviceSet* deviceSet = deviceSets[channel->getDeviceSetIndex()]; QString deviceSetId = getDeviceSetId(deviceSet); int index = channel->getIndexInDeviceSet(); - // FIXME: if (deviceSet->m_deviceMIMOEngine) { - // we should append stream index. E.g. "M0:0.0" However, only ChannelGUI seems to know what it is - return QString("%1:%2").arg(deviceSetId).arg(index); + if (deviceSet->m_deviceMIMOEngine) { + return QString("%1:%2.%3").arg(deviceSetId).arg(index).arg(channel->getStreamIndex()); + } else { + return QString("%1:%2").arg(deviceSetId).arg(index); + } } QStringList MainCore::getDeviceSetIds(bool rx, bool tx, bool mimo) diff --git a/sdrbase/maincore.h b/sdrbase/maincore.h index ee3e1e569..410322d6e 100644 --- a/sdrbase/maincore.h +++ b/sdrbase/maincore.h @@ -38,6 +38,7 @@ #include "pipes/messagepipes.h" #include "pipes/datapipes.h" #include "channel/channelapi.h" +#include "availablechannelorfeature.h" class DeviceSet; class FeatureSet; @@ -59,6 +60,7 @@ namespace SWGSDRangel class SWGStarTrackerTarget; class SWGStarTrackerDisplaySettings; class SWGStarTrackerDisplayLoSSettings; + class SWGSkyMapTarget; } class SDRBASE_API MainCore : public QObject @@ -842,7 +844,28 @@ public: { } }; + class SDRBASE_API MsgSkyMapTarget : public Message { + MESSAGE_CLASS_DECLARATION + public: + const QObject *getPipeSource() const { return m_pipeSource; } + SWGSDRangel::SWGSkyMapTarget *getSWGSkyMapTarget() const { return m_swgSkyMapTarget; } + + static MsgSkyMapTarget* create(const QObject *pipeSource, SWGSDRangel::SWGSkyMapTarget *swgSkyMapTarget) + { + return new MsgSkyMapTarget(pipeSource, swgSkyMapTarget); + } + + private: + const QObject *m_pipeSource; + SWGSDRangel::SWGSkyMapTarget *m_swgSkyMapTarget; + + MsgSkyMapTarget(const QObject *pipeSource, SWGSDRangel::SWGSkyMapTarget *swgSkyMapTarget) : + Message(), + m_pipeSource(pipeSource), + m_swgSkyMapTarget(swgSkyMapTarget) + { } + }; MainCore(); ~MainCore(); @@ -886,6 +909,11 @@ public: // Position const QGeoPositionInfo& getPosition() const; + // Lists of available channels and features. List should be ordered by indexes. Plugins should use AvailableChannelOrFeatureHandler to maintain this list + AvailableChannelOrFeatureList getAvailableChannels(const QStringList& uris); // Get list of available channels with given URIs or all if empty list. + AvailableChannelOrFeatureList getAvailableFeatures(const QStringList& uris); // Get list of available features with given URIs or all if empty list. + AvailableChannelOrFeatureList getAvailableChannelsAndFeatures(const QStringList& uris, const QString& kinds); // Get list of available channels and features with given URIs or all if empty list. + // Ids QChar getDeviceSetTypeId(const DeviceSet* deviceSet); //!< Get Type Id (E.g. 'R', 'T' or 'M') for the given device set QString getDeviceSetId(const DeviceSet* deviceSet); //!< Get Id (E.g. "R2") for the given device set diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 0675d2d30..d13a80921 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -6249,6 +6249,9 @@ margin-bottom: 20px; "SimplePTTActions" : { "$ref" : "#/definitions/SimplePTTActions" }, + "SkyMapActions" : { + "$ref" : "#/definitions/SkyMapActions" + }, "StarTrackerActions" : { "$ref" : "#/definitions/StarTrackerActions" }, @@ -6394,6 +6397,9 @@ margin-bottom: 20px; "SimplePTTReport" : { "$ref" : "#/definitions/SimplePTTReport" }, + "SkyMapReport" : { + "$ref" : "#/definitions/SkyMapReport" + }, "StarTrackerReport" : { "$ref" : "#/definitions/StarTrackerReport" }, @@ -6495,12 +6501,15 @@ margin-bottom: 20px; "SatelliteTrackerSettings" : { "$ref" : "#/definitions/SatelliteTrackerSettings" }, - "StarTrackerSettings" : { - "$ref" : "#/definitions/StarTrackerSettings" - }, "SimplePTTSettings" : { "$ref" : "#/definitions/SimplePTTSettings" }, + "SkyMapSettings" : { + "$ref" : "#/definitions/SkyMapSettings" + }, + "StarTrackerSettings" : { + "$ref" : "#/definitions/StarTrackerSettings" + }, "VORLocalizerSettings" : { "$ref" : "#/definitions/VORLocalizerSettings" } @@ -14618,6 +14627,236 @@ margin-bottom: 20px; } }, "description" : "Simple PTT settings" +}; + defs.SkyMapActions = { + "properties" : { + "find" : { + "type" : "string", + "description" : "The name of the object or the coordinates to centre the sky map on" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapReport = { + "properties" : { + "dateTime" : { + "type" : "string", + "description" : "Current date and time being used for sky map" + }, + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "azimuth" : { + "type" : "number", + "format" : "float", + "description" : "The azimuth angle in degrees to the target" + }, + "elevation" : { + "type" : "number", + "format" : "float", + "description" : "The elevation angle in degrees to the target" + }, + "fov" : { + "type" : "number", + "format" : "float", + "description" : "Current field-of-view in degrees" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapSettings = { + "properties" : { + "displayNames" : { + "type" : "integer", + "description" : "Display names on the sky map (1 for yes, 0 for no)" + }, + "displayConstellations" : { + "type" : "integer", + "description" : "Display constellations on the sky map (1 for yes, 0 for no)" + }, + "displayReticle" : { + "type" : "integer", + "description" : "Display reticle on the sky map (1 for yes, 0 for no)" + }, + "displayGrid" : { + "type" : "integer", + "description" : "Display grid on the sky map (1 for yes, 0 for no)" + }, + "displayAntennaFoV" : { + "type" : "integer", + "description" : "Display antenna field-of-view on the sky map (1 for yes, 0 for no)" + }, + "map" : { + "type" : "string", + "description" : "WWT, ESASky or Aladin" + }, + "background" : { + "type" : "string", + "description" : "Name of background image set" + }, + "projection" : { + "type" : "string" + }, + "source" : { + "type" : "string", + "description" : "Channel or Feature plugin to get target from" + }, + "track" : { + "type" : "integer", + "description" : "Whether to track the specified source plugin" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "useMyPosition" : { + "type" : "number", + "format" : "float", + "description" : "Use My Position instead of latitude/longitude settings" + }, + "title" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIFeatureSetIndex" : { + "type" : "integer" + }, + "reverseAPIFeatureIndex" : { + "type" : "integer" + }, + "rollupState" : { + "$ref" : "#/definitions/RollupState" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapTarget = { + "properties" : { + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "dateTime" : { + "type" : "string", + "description" : "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + } + }, + "description" : "Sky Map target. Sent by other plugins to skymap.target message queue." +}; + defs.SkyMapTarget_2 = { + "properties" : { + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "dateTime" : { + "type" : "string", + "description" : "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + } + }, + "description" : "Sky Map target. Sent by other plugins to skymap.target message queue." }; defs.SoapySDRFrequencySetting = { "properties" : { @@ -58429,7 +58668,7 @@ except ApiException as e:
- Generated 2024-01-21T13:22:02.160+01:00 + Generated 2024-02-12T10:33:45.606+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml index d46ccf17b..75003fcb3 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureActions.yaml @@ -31,6 +31,8 @@ FeatureActions: $ref: "/doc/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerActions" SimplePTTActions: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTActions" + SkyMapActions: + $ref: "/doc/swagger/include/SkyMap.yaml#/SkyMapActions" StarTrackerActions: $ref: "/doc/swagger/include/StarTracker.yaml#/StarTrackerActions" VORLocalizerActions: diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml index c4c63649e..20cfbd37e 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureReport.yaml @@ -25,6 +25,8 @@ FeatureReport: $ref: "/doc/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerReport" SimplePTTReport: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTReport" + SkyMapReport: + $ref: "/doc/swagger/include/SkyMap.yaml#/SkyMapReport" StarTrackerReport: $ref: "/doc/swagger/include/StarTracker.yaml#/StarTrackerReport" VORLocalizerReport: diff --git a/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml index 2bef41e84..c5a5b5eea 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/FeatureSettings.yaml @@ -41,9 +41,11 @@ FeatureSettings: $ref: "/doc/swagger/include/RigCtlServer.yaml#/RigCtlServerSettings" SatelliteTrackerSettings: $ref: "/doc/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerSettings" - StarTrackerSettings: - $ref: "/doc/swagger/include/StarTracker.yaml#/StarTrackerSettings" SimplePTTSettings: $ref: "/doc/swagger/include/SimplePTT.yaml#/SimplePTTSettings" + SkyMapSettings: + $ref: "/doc/swagger/include/SkyMap.yaml#/SkyMapSettings" + StarTrackerSettings: + $ref: "/doc/swagger/include/StarTracker.yaml#/StarTrackerSettings" VORLocalizerSettings: $ref: "/doc/swagger/include/VORLocalizer.yaml#/VORLocalizerSettings" diff --git a/sdrbase/resources/webapi/doc/swagger/include/SkyMap.yaml b/sdrbase/resources/webapi/doc/swagger/include/SkyMap.yaml new file mode 100644 index 000000000..1ef724a9f --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/SkyMap.yaml @@ -0,0 +1,146 @@ +SkyMapSettings: + description: Sky Map + properties: + displayNames: + description: "Display names on the sky map (1 for yes, 0 for no)" + type: integer + displayConstellations: + description: "Display constellations on the sky map (1 for yes, 0 for no)" + type: integer + displayReticle: + description: "Display reticle on the sky map (1 for yes, 0 for no)" + type: integer + displayGrid: + description: "Display grid on the sky map (1 for yes, 0 for no)" + type: integer + displayAntennaFoV: + description: "Display antenna field-of-view on the sky map (1 for yes, 0 for no)" + type: integer + map: + description: "WWT, ESASky or Aladin" + type: string + background: + description: "Name of background image set" + type: string + projection: + type: string + source: + description: "Channel or Feature plugin to get target from" + type: string + track: + description: "Whether to track the specified source plugin" + type: integer + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + hpbw: + description: "Antenna half-power beam width in degrees" + type: number + format: float + useMyPosition: + description: "Use My Position instead of latitude/longitude settings" + type: number + format: float + title: + type: string + rgbColor: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIFeatureSetIndex: + type: integer + reverseAPIFeatureIndex: + type: integer + rollupState: + $ref: "/doc/swagger/include/RollupState.yaml#/RollupState" + +SkyMapReport: + description: Sky Map + properties: + dateTime: + description: "Current date and time being used for sky map" + type: string + ra: + description: "Right ascension of target (In decimal hours, J2000)" + type: number + format: float + dec: + description: "Declination of target (In decimal degrees, J2000)" + type: number + format: float + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + azimuth: + description: "The azimuth angle in degrees to the target" + type: number + format: float + elevation: + description: "The elevation angle in degrees to the target" + type: number + format: float + fov: + description: "Current field-of-view in degrees" + type: number + format: float + +SkyMapActions: + description: Sky Map + properties: + find: + description: "The name of the object or the coordinates to centre the sky map on" + type: string + +SkyMapTarget: + description: "Sky Map target. Sent by other plugins to skymap.target message queue." + properties: + ra: + description: "Right ascension of target (In decimal hours, J2000)" + type: number + format: float + dec: + description: "Declination of target (In decimal degrees, J2000)" + type: number + format: float + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + hpbw: + description: "Antenna half-power beam width in degrees" + type: number + format: float + dateTime: + description: "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + type: string diff --git a/sdrbase/resources/webapi/doc/swagger/swagger.yaml b/sdrbase/resources/webapi/doc/swagger/swagger.yaml index 28e6d17ff..43511de31 100644 --- a/sdrbase/resources/webapi/doc/swagger/swagger.yaml +++ b/sdrbase/resources/webapi/doc/swagger/swagger.yaml @@ -3263,6 +3263,10 @@ definitions: StarTrackerDisplayLoSSettings: $ref: "/doc/swagger/include/StarTracker.yaml#/StarTrackerDisplayLoSSettings" + # Sky Map target passed from Star Tracker plugin + SkyMapTarget: + $ref: "/doc/swagger/include/SkyMap.yaml#/SkyMapTarget" + # This isn't in GS232Controller, as it may eventually be used by other controllers or features TargetAzimuthElevation: description: "A target azimuth and elevation" diff --git a/sdrbase/util/units.h b/sdrbase/util/units.h index 8ff59e84b..59ad21f6d 100644 --- a/sdrbase/util/units.h +++ b/sdrbase/util/units.h @@ -339,6 +339,43 @@ public: return false; } + // Try to convert a string to Right Ascension (RA) and Declination. Returns false if not recognised format. + // This supports HMS/DMS or decimal. + // E.g.: + // 12 05 12.23 +17 06 21.0 + // 12:05:12.23 -17:06:21.0 + // 12h05m12.23s +17d06m21.0s + // 107.1324 -34.233 + static bool stringToRADec(const QString& string, float& ra, float& dec) + { + QRegExp dms("([0-9]+)[ :h]([0-9]+)[ :m]([0-9]+(\\.[0-9]+)?)s? *,? *([+-]?[0-9]+)[ :d]([0-9]+)[ :m]([0-9]+(\\.[0-9]+)?)s?"); + if (dms.exactMatch(string)) + { + int raHours = dms.capturedTexts()[1].toInt(); + int raMins = dms.capturedTexts()[2].toInt(); + float raSecs = dms.capturedTexts()[3].toFloat(); + ra = raHours + raMins / 60.0f + raSecs / (60.0f * 60.0f); + qDebug() << ra << raHours << raMins << raSecs; + int decDegs = dms.capturedTexts()[5].toInt(); + int decMins = dms.capturedTexts()[6].toInt(); + float decSecs = dms.capturedTexts()[7].toFloat(); + bool neg = decDegs < 0; + dec = abs(decDegs) + decMins / 60.0f + decSecs / (60.0f * 60.0f); + if (neg) { + dec = -dec; + } + return true; + } + QRegExp decimal("([0-9]+(\\.[0-9]+)?) *,? *([+-]?[0-9]+(\\.[0-9]+)?)"); + if (decimal.exactMatch(string)) + { + ra = decimal.capturedTexts()[1].toFloat(); + dec = decimal.capturedTexts()[3].toFloat(); + return true; + } + return false; + } + static float solarFluxUnitsToJansky(float sfu) { return sfu * 10000.0f; diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 2e90c726c..675faa6af 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -5273,6 +5273,11 @@ bool WebAPIRequestMapper::getFeatureSettings( featureSettings->setSimplePttSettings(new SWGSDRangel::SWGSimplePTTSettings()); featureSettings->getSimplePttSettings()->fromJsonObject(settingsJsonObject); } + else if (featureSettingsKey == "SkyMapSettings") + { + featureSettings->setSkyMapSettings(new SWGSDRangel::SWGSkyMapSettings()); + featureSettings->getSkyMapSettings()->fromJsonObject(settingsJsonObject); + } else if (featureSettingsKey == "StarTrackerSettings") { featureSettings->setStarTrackerSettings(new SWGSDRangel::SWGStarTrackerSettings()); @@ -5366,6 +5371,11 @@ bool WebAPIRequestMapper::getFeatureActions( featureActions->setSimplePttActions(new SWGSDRangel::SWGSimplePTTActions()); featureActions->getSimplePttActions()->fromJsonObject(actionsJsonObject); } + else if (featureActionsKey == "SkyMapActions") + { + featureActions->setSkyMapActions(new SWGSDRangel::SWGSkyMapActions()); + featureActions->getSkyMapActions()->fromJsonObject(actionsJsonObject); + } else if (featureActionsKey == "StarTrackerActions") { featureActions->setStarTrackerActions(new SWGSDRangel::SWGStarTrackerActions()); @@ -5376,7 +5386,7 @@ bool WebAPIRequestMapper::getFeatureActions( featureActions->setVorLocalizerActions(new SWGSDRangel::SWGVORLocalizerActions()); featureActions->getVorLocalizerActions()->fromJsonObject(actionsJsonObject); } - else if (featureActionsKey == "DemodAnalyzerActions") + else if (featureActionsKey == "DemodAnalyzerActions") { featureActions->setDemodAnalyzerActions(new SWGSDRangel::SWGDemodAnalyzerActions()); featureActions->getDemodAnalyzerActions()->fromJsonObject(actionsJsonObject); @@ -5623,6 +5633,7 @@ void WebAPIRequestMapper::resetFeatureSettings(SWGSDRangel::SWGFeatureSettings& featureSettings.setPerTesterSettings(nullptr); featureSettings.setSatelliteTrackerSettings(nullptr); featureSettings.setSimplePttSettings(nullptr); + featureSettings.setSkyMapSettings(nullptr); featureSettings.setStarTrackerSettings(nullptr); featureSettings.setRadiosondeSettings(nullptr); featureSettings.setRigCtlServerSettings(nullptr); @@ -5639,6 +5650,7 @@ void WebAPIRequestMapper::resetFeatureReport(SWGSDRangel::SWGFeatureReport& feat featureReport.setMapReport(nullptr); featureReport.setSatelliteTrackerReport(nullptr); featureReport.setSimplePttReport(nullptr); + featureReport.setSkyMapReport(nullptr); featureReport.setStarTrackerReport(nullptr); featureReport.setVorLocalizerReport(nullptr); } @@ -5654,6 +5666,7 @@ void WebAPIRequestMapper::resetFeatureActions(SWGSDRangel::SWGFeatureActions& fe featureActions.setRigCtlServerActions(nullptr); featureActions.setSatelliteTrackerActions(nullptr); featureActions.setSimplePttActions(nullptr); + featureActions.setSkyMapActions(nullptr); featureActions.setStarTrackerActions(nullptr); featureActions.setVorLocalizerActions(nullptr); } diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index 857de129c..d0a524330 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -320,6 +320,7 @@ const QMap WebAPIUtils::m_featureTypeToSettingsKey = { {"RigCtlServer", "RigCtlServerSettings"}, {"SatelliteTracker", "SatelliteTrackerSettings"}, {"SimplePTT", "SimplePTTSettings"}, + {"SkyMap", "SkyMapSettings"}, {"StarTracker", "StarTrackerSettings"}, {"VORLocalizer", "VORLocalizerSettings"} }; @@ -334,6 +335,7 @@ const QMap WebAPIUtils::m_featureTypeToActionsKey = { {"RigCtlServer", "RigCtlServerActions"}, {"SatelliteTracker", "SatelliteTrackerActions"}, {"SimplePTT", "SimplePTTActions"}, + {"SkyMap", "SkyMapActions"}, {"StarTracker", "StarTrackerActions"}, {"VORLocalizer", "VORLocalizerActions"}, {"DemodAnalyzer", "DemodAnalyzerActions"} @@ -355,6 +357,7 @@ const QMap WebAPIUtils::m_featureURIToSettingsKey = { {"sdrangel.feature.rigctlserver", "RigCtlServerSettings"}, {"sdrangel.feature.satellitetracker", "SatelliteTrackerSettings"}, {"sdrangel.feature.simpleptt", "SimplePTTSettings"}, + {"sdrangel.feature.skymap", "SkyMapSettings"}, {"sdrangel.feature.startracker", "StarTrackerSettings"}, {"sdrangel.feature.vorlocalizer", "VORLocalizerSettings"} }; diff --git a/sdrgui/feature/featuregui.cpp b/sdrgui/feature/featuregui.cpp index 4bb61b9a8..123a26edb 100644 --- a/sdrgui/feature/featuregui.cpp +++ b/sdrgui/feature/featuregui.cpp @@ -417,3 +417,8 @@ void FeatureGUI::setDisplayedame(const QString& name) m_displayedName = name; m_indexLabel->setToolTip(tr("%1").arg(m_displayedName)); } + +void FeatureGUI::setStatusText(const QString& text) +{ + m_statusLabel->setText(text); +} diff --git a/sdrgui/feature/featuregui.h b/sdrgui/feature/featuregui.h index 1fc507d63..ebc72f8ae 100644 --- a/sdrgui/feature/featuregui.h +++ b/sdrgui/feature/featuregui.h @@ -68,6 +68,7 @@ public: void setIndex(int index); int getIndex() const { return m_featureIndex; } void setDisplayedame(const QString& name); + void setStatusText(const QString& text); protected: void closeEvent(QCloseEvent *event) override; diff --git a/sdrgui/gui/int64validator.cpp b/sdrgui/gui/int64validator.cpp index 09d2863dc..92ee6dddb 100644 --- a/sdrgui/gui/int64validator.cpp +++ b/sdrgui/gui/int64validator.cpp @@ -19,6 +19,8 @@ QValidator::State Int64Validator::validate(QString& input, int &pos) const { + (void) pos; + if (input == "") { return QValidator::Acceptable; } diff --git a/swagger/sdrangel/api/swagger/include/FeatureActions.yaml b/swagger/sdrangel/api/swagger/include/FeatureActions.yaml index b19942023..562154a38 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureActions.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureActions.yaml @@ -31,6 +31,8 @@ FeatureActions: $ref: "http://swgserver:8081/api/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerActions" SimplePTTActions: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTActions" + SkyMapActions: + $ref: "http://swgserver:8081/api/swagger/include/SkyMap.yaml#/SkyMapActions" StarTrackerActions: $ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerActions" VORLocalizerActions: diff --git a/swagger/sdrangel/api/swagger/include/FeatureReport.yaml b/swagger/sdrangel/api/swagger/include/FeatureReport.yaml index 95fdcea9e..67e19d0ea 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureReport.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureReport.yaml @@ -25,6 +25,8 @@ FeatureReport: $ref: "http://swgserver:8081/api/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerReport" SimplePTTReport: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTReport" + SkyMapReport: + $ref: "http://swgserver:8081/api/swagger/include/SkyMap.yaml#/SkyMapReport" StarTrackerReport: $ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerReport" VORLocalizerReport: diff --git a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml index 6832f8ab4..96929de07 100644 --- a/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/FeatureSettings.yaml @@ -41,9 +41,11 @@ FeatureSettings: $ref: "http://swgserver:8081/api/swagger/include/RigCtlServer.yaml#/RigCtlServerSettings" SatelliteTrackerSettings: $ref: "http://swgserver:8081/api/swagger/include/SatelliteTracker.yaml#/SatelliteTrackerSettings" - StarTrackerSettings: - $ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerSettings" SimplePTTSettings: $ref: "http://swgserver:8081/api/swagger/include/SimplePTT.yaml#/SimplePTTSettings" + SkyMapSettings: + $ref: "http://swgserver:8081/api/swagger/include/SkyMap.yaml#/SkyMapSettings" + StarTrackerSettings: + $ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerSettings" VORLocalizerSettings: $ref: "http://swgserver:8081/api/swagger/include/VORLocalizer.yaml#/VORLocalizerSettings" diff --git a/swagger/sdrangel/api/swagger/include/SkyMap.yaml b/swagger/sdrangel/api/swagger/include/SkyMap.yaml new file mode 100644 index 000000000..5fc620230 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/SkyMap.yaml @@ -0,0 +1,146 @@ +SkyMapSettings: + description: Sky Map + properties: + displayNames: + description: "Display names on the sky map (1 for yes, 0 for no)" + type: integer + displayConstellations: + description: "Display constellations on the sky map (1 for yes, 0 for no)" + type: integer + displayReticle: + description: "Display reticle on the sky map (1 for yes, 0 for no)" + type: integer + displayGrid: + description: "Display grid on the sky map (1 for yes, 0 for no)" + type: integer + displayAntennaFoV: + description: "Display antenna field-of-view on the sky map (1 for yes, 0 for no)" + type: integer + map: + description: "WWT, ESASky or Aladin" + type: string + background: + description: "Name of background image set" + type: string + projection: + type: string + source: + description: "Channel or Feature plugin to get target from" + type: string + track: + description: "Whether to track the specified source plugin" + type: integer + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + hpbw: + description: "Antenna half-power beam width in degrees" + type: number + format: float + useMyPosition: + description: "Use My Position instead of latitude/longitude settings" + type: number + format: float + title: + type: string + rgbColor: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIFeatureSetIndex: + type: integer + reverseAPIFeatureIndex: + type: integer + rollupState: + $ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState" + +SkyMapReport: + description: Sky Map + properties: + dateTime: + description: "Current date and time being used for sky map" + type: string + ra: + description: "Right ascension of target (In decimal hours, J2000)" + type: number + format: float + dec: + description: "Declination of target (In decimal degrees, J2000)" + type: number + format: float + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + azimuth: + description: "The azimuth angle in degrees to the target" + type: number + format: float + elevation: + description: "The elevation angle in degrees to the target" + type: number + format: float + fov: + description: "Current field-of-view in degrees" + type: number + format: float + +SkyMapActions: + description: Sky Map + properties: + find: + description: "The name of the object or the coordinates to centre the sky map on" + type: string + +SkyMapTarget: + description: "Sky Map target. Sent by other plugins to skymap.target message queue." + properties: + ra: + description: "Right ascension of target (In decimal hours, J2000)" + type: number + format: float + dec: + description: "Declination of target (In decimal degrees, J2000)" + type: number + format: float + latitude: + description: "Latitude in decimal degrees (North positive) of observation/antenna location" + type: number + format: float + longitude: + description: "Longitude in decimal degrees (East positive) of observation/antenna location" + type: number + format: float + altitude: + description: "Altitude in metres of observation/antenna location" + type: number + format: float + hpbw: + description: "Antenna half-power beam width in degrees" + type: number + format: float + dateTime: + description: "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + type: string diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml index 3bc1a4173..342397bca 100644 --- a/swagger/sdrangel/api/swagger/swagger.yaml +++ b/swagger/sdrangel/api/swagger/swagger.yaml @@ -3263,6 +3263,10 @@ definitions: StarTrackerDisplayLoSSettings: $ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerDisplayLoSSettings" + # Sky Map target passed from Star Tracker plugin + SkyMapTarget: + $ref: "http://swgserver:8081/api/swagger/include/SkyMap.yaml#/SkyMapTarget" + # This isn't in GS232Controller, as it may eventually be used by other controllers or features TargetAzimuthElevation: description: "A target azimuth and elevation" diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 0675d2d30..d13a80921 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -6249,6 +6249,9 @@ margin-bottom: 20px; "SimplePTTActions" : { "$ref" : "#/definitions/SimplePTTActions" }, + "SkyMapActions" : { + "$ref" : "#/definitions/SkyMapActions" + }, "StarTrackerActions" : { "$ref" : "#/definitions/StarTrackerActions" }, @@ -6394,6 +6397,9 @@ margin-bottom: 20px; "SimplePTTReport" : { "$ref" : "#/definitions/SimplePTTReport" }, + "SkyMapReport" : { + "$ref" : "#/definitions/SkyMapReport" + }, "StarTrackerReport" : { "$ref" : "#/definitions/StarTrackerReport" }, @@ -6495,12 +6501,15 @@ margin-bottom: 20px; "SatelliteTrackerSettings" : { "$ref" : "#/definitions/SatelliteTrackerSettings" }, - "StarTrackerSettings" : { - "$ref" : "#/definitions/StarTrackerSettings" - }, "SimplePTTSettings" : { "$ref" : "#/definitions/SimplePTTSettings" }, + "SkyMapSettings" : { + "$ref" : "#/definitions/SkyMapSettings" + }, + "StarTrackerSettings" : { + "$ref" : "#/definitions/StarTrackerSettings" + }, "VORLocalizerSettings" : { "$ref" : "#/definitions/VORLocalizerSettings" } @@ -14618,6 +14627,236 @@ margin-bottom: 20px; } }, "description" : "Simple PTT settings" +}; + defs.SkyMapActions = { + "properties" : { + "find" : { + "type" : "string", + "description" : "The name of the object or the coordinates to centre the sky map on" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapReport = { + "properties" : { + "dateTime" : { + "type" : "string", + "description" : "Current date and time being used for sky map" + }, + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "azimuth" : { + "type" : "number", + "format" : "float", + "description" : "The azimuth angle in degrees to the target" + }, + "elevation" : { + "type" : "number", + "format" : "float", + "description" : "The elevation angle in degrees to the target" + }, + "fov" : { + "type" : "number", + "format" : "float", + "description" : "Current field-of-view in degrees" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapSettings = { + "properties" : { + "displayNames" : { + "type" : "integer", + "description" : "Display names on the sky map (1 for yes, 0 for no)" + }, + "displayConstellations" : { + "type" : "integer", + "description" : "Display constellations on the sky map (1 for yes, 0 for no)" + }, + "displayReticle" : { + "type" : "integer", + "description" : "Display reticle on the sky map (1 for yes, 0 for no)" + }, + "displayGrid" : { + "type" : "integer", + "description" : "Display grid on the sky map (1 for yes, 0 for no)" + }, + "displayAntennaFoV" : { + "type" : "integer", + "description" : "Display antenna field-of-view on the sky map (1 for yes, 0 for no)" + }, + "map" : { + "type" : "string", + "description" : "WWT, ESASky or Aladin" + }, + "background" : { + "type" : "string", + "description" : "Name of background image set" + }, + "projection" : { + "type" : "string" + }, + "source" : { + "type" : "string", + "description" : "Channel or Feature plugin to get target from" + }, + "track" : { + "type" : "integer", + "description" : "Whether to track the specified source plugin" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "useMyPosition" : { + "type" : "number", + "format" : "float", + "description" : "Use My Position instead of latitude/longitude settings" + }, + "title" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIFeatureSetIndex" : { + "type" : "integer" + }, + "reverseAPIFeatureIndex" : { + "type" : "integer" + }, + "rollupState" : { + "$ref" : "#/definitions/RollupState" + } + }, + "description" : "Sky Map" +}; + defs.SkyMapTarget = { + "properties" : { + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "dateTime" : { + "type" : "string", + "description" : "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + } + }, + "description" : "Sky Map target. Sent by other plugins to skymap.target message queue." +}; + defs.SkyMapTarget_2 = { + "properties" : { + "ra" : { + "type" : "number", + "format" : "float", + "description" : "Right ascension of target (In decimal hours, J2000)" + }, + "dec" : { + "type" : "number", + "format" : "float", + "description" : "Declination of target (In decimal degrees, J2000)" + }, + "latitude" : { + "type" : "number", + "format" : "float", + "description" : "Latitude in decimal degrees (North positive) of observation/antenna location" + }, + "longitude" : { + "type" : "number", + "format" : "float", + "description" : "Longitude in decimal degrees (East positive) of observation/antenna location" + }, + "altitude" : { + "type" : "number", + "format" : "float", + "description" : "Altitude in metres of observation/antenna location" + }, + "hpbw" : { + "type" : "number", + "format" : "float", + "description" : "Antenna half-power beam width in degrees" + }, + "dateTime" : { + "type" : "string", + "description" : "Date and time of observation. ISO 8601 extended format: yyyy-MM-ddTHH:mm:ss with Z suffix for UTC. Empty string for current time." + } + }, + "description" : "Sky Map target. Sent by other plugins to skymap.target message queue." }; defs.SoapySDRFrequencySetting = { "properties" : { @@ -58429,7 +58668,7 @@ except ApiException as e:
- Generated 2024-01-21T13:22:02.160+01:00 + Generated 2024-02-12T10:33:45.606+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp index e3a91bee7..f8d5c86dd 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.cpp @@ -52,6 +52,8 @@ SWGFeatureActions::SWGFeatureActions() { m_satellite_tracker_actions_isSet = false; simple_ptt_actions = nullptr; m_simple_ptt_actions_isSet = false; + sky_map_actions = nullptr; + m_sky_map_actions_isSet = false; star_tracker_actions = nullptr; m_star_tracker_actions_isSet = false; vor_localizer_actions = nullptr; @@ -90,6 +92,8 @@ SWGFeatureActions::init() { m_satellite_tracker_actions_isSet = false; simple_ptt_actions = new SWGSimplePTTActions(); m_simple_ptt_actions_isSet = false; + sky_map_actions = new SWGSkyMapActions(); + m_sky_map_actions_isSet = false; star_tracker_actions = new SWGStarTrackerActions(); m_star_tracker_actions_isSet = false; vor_localizer_actions = new SWGVORLocalizerActions(); @@ -132,6 +136,9 @@ SWGFeatureActions::cleanup() { if(simple_ptt_actions != nullptr) { delete simple_ptt_actions; } + if(sky_map_actions != nullptr) { + delete sky_map_actions; + } if(star_tracker_actions != nullptr) { delete star_tracker_actions; } @@ -178,6 +185,8 @@ SWGFeatureActions::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&simple_ptt_actions, pJson["SimplePTTActions"], "SWGSimplePTTActions", "SWGSimplePTTActions"); + ::SWGSDRangel::setValue(&sky_map_actions, pJson["SkyMapActions"], "SWGSkyMapActions", "SWGSkyMapActions"); + ::SWGSDRangel::setValue(&star_tracker_actions, pJson["StarTrackerActions"], "SWGStarTrackerActions", "SWGStarTrackerActions"); ::SWGSDRangel::setValue(&vor_localizer_actions, pJson["VORLocalizerActions"], "SWGVORLocalizerActions", "SWGVORLocalizerActions"); @@ -236,6 +245,9 @@ SWGFeatureActions::asJsonObject() { if((simple_ptt_actions != nullptr) && (simple_ptt_actions->isSet())){ toJsonValue(QString("SimplePTTActions"), simple_ptt_actions, obj, QString("SWGSimplePTTActions")); } + if((sky_map_actions != nullptr) && (sky_map_actions->isSet())){ + toJsonValue(QString("SkyMapActions"), sky_map_actions, obj, QString("SWGSkyMapActions")); + } if((star_tracker_actions != nullptr) && (star_tracker_actions->isSet())){ toJsonValue(QString("StarTrackerActions"), star_tracker_actions, obj, QString("SWGStarTrackerActions")); } @@ -369,6 +381,16 @@ SWGFeatureActions::setSimplePttActions(SWGSimplePTTActions* simple_ptt_actions) this->m_simple_ptt_actions_isSet = true; } +SWGSkyMapActions* +SWGFeatureActions::getSkyMapActions() { + return sky_map_actions; +} +void +SWGFeatureActions::setSkyMapActions(SWGSkyMapActions* sky_map_actions) { + this->sky_map_actions = sky_map_actions; + this->m_sky_map_actions_isSet = true; +} + SWGStarTrackerActions* SWGFeatureActions::getStarTrackerActions() { return star_tracker_actions; @@ -440,6 +462,9 @@ SWGFeatureActions::isSet(){ if(simple_ptt_actions && simple_ptt_actions->isSet()){ isObjectUpdated = true; break; } + if(sky_map_actions && sky_map_actions->isSet()){ + isObjectUpdated = true; break; + } if(star_tracker_actions && star_tracker_actions->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h index 065ff5a41..971933eca 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureActions.h @@ -32,6 +32,7 @@ #include "SWGRigCtlServerActions.h" #include "SWGSatelliteTrackerActions.h" #include "SWGSimplePTTActions.h" +#include "SWGSkyMapActions.h" #include "SWGStarTrackerActions.h" #include "SWGVORLocalizerActions.h" #include @@ -90,6 +91,9 @@ public: SWGSimplePTTActions* getSimplePttActions(); void setSimplePttActions(SWGSimplePTTActions* simple_ptt_actions); + SWGSkyMapActions* getSkyMapActions(); + void setSkyMapActions(SWGSkyMapActions* sky_map_actions); + SWGStarTrackerActions* getStarTrackerActions(); void setStarTrackerActions(SWGStarTrackerActions* star_tracker_actions); @@ -139,6 +143,9 @@ private: SWGSimplePTTActions* simple_ptt_actions; bool m_simple_ptt_actions_isSet; + SWGSkyMapActions* sky_map_actions; + bool m_sky_map_actions_isSet; + SWGStarTrackerActions* star_tracker_actions; bool m_star_tracker_actions_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp index 087a514f0..05da233d8 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.cpp @@ -48,6 +48,8 @@ SWGFeatureReport::SWGFeatureReport() { m_satellite_tracker_report_isSet = false; simple_ptt_report = nullptr; m_simple_ptt_report_isSet = false; + sky_map_report = nullptr; + m_sky_map_report_isSet = false; star_tracker_report = nullptr; m_star_tracker_report_isSet = false; vor_localizer_report = nullptr; @@ -80,6 +82,8 @@ SWGFeatureReport::init() { m_satellite_tracker_report_isSet = false; simple_ptt_report = new SWGSimplePTTReport(); m_simple_ptt_report_isSet = false; + sky_map_report = new SWGSkyMapReport(); + m_sky_map_report_isSet = false; star_tracker_report = new SWGStarTrackerReport(); m_star_tracker_report_isSet = false; vor_localizer_report = new SWGVORLocalizerReport(); @@ -118,6 +122,9 @@ SWGFeatureReport::cleanup() { if(simple_ptt_report != nullptr) { delete simple_ptt_report; } + if(sky_map_report != nullptr) { + delete sky_map_report; + } if(star_tracker_report != nullptr) { delete star_tracker_report; } @@ -157,6 +164,8 @@ SWGFeatureReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&simple_ptt_report, pJson["SimplePTTReport"], "SWGSimplePTTReport", "SWGSimplePTTReport"); + ::SWGSDRangel::setValue(&sky_map_report, pJson["SkyMapReport"], "SWGSkyMapReport", "SWGSkyMapReport"); + ::SWGSDRangel::setValue(&star_tracker_report, pJson["StarTrackerReport"], "SWGStarTrackerReport", "SWGStarTrackerReport"); ::SWGSDRangel::setValue(&vor_localizer_report, pJson["VORLocalizerReport"], "SWGVORLocalizerReport", "SWGVORLocalizerReport"); @@ -207,6 +216,9 @@ SWGFeatureReport::asJsonObject() { if((simple_ptt_report != nullptr) && (simple_ptt_report->isSet())){ toJsonValue(QString("SimplePTTReport"), simple_ptt_report, obj, QString("SWGSimplePTTReport")); } + if((sky_map_report != nullptr) && (sky_map_report->isSet())){ + toJsonValue(QString("SkyMapReport"), sky_map_report, obj, QString("SWGSkyMapReport")); + } if((star_tracker_report != nullptr) && (star_tracker_report->isSet())){ toJsonValue(QString("StarTrackerReport"), star_tracker_report, obj, QString("SWGStarTrackerReport")); } @@ -317,6 +329,16 @@ SWGFeatureReport::setSimplePttReport(SWGSimplePTTReport* simple_ptt_report) { this->m_simple_ptt_report_isSet = true; } +SWGSkyMapReport* +SWGFeatureReport::getSkyMapReport() { + return sky_map_report; +} +void +SWGFeatureReport::setSkyMapReport(SWGSkyMapReport* sky_map_report) { + this->sky_map_report = sky_map_report; + this->m_sky_map_report_isSet = true; +} + SWGStarTrackerReport* SWGFeatureReport::getStarTrackerReport() { return star_tracker_report; @@ -372,6 +394,9 @@ SWGFeatureReport::isSet(){ if(simple_ptt_report && simple_ptt_report->isSet()){ isObjectUpdated = true; break; } + if(sky_map_report && sky_map_report->isSet()){ + isObjectUpdated = true; break; + } if(star_tracker_report && star_tracker_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h index 563e26163..d30819af9 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureReport.h @@ -31,6 +31,7 @@ #include "SWGRigCtlServerReport.h" #include "SWGSatelliteTrackerReport.h" #include "SWGSimplePTTReport.h" +#include "SWGSkyMapReport.h" #include "SWGStarTrackerReport.h" #include "SWGVORLocalizerReport.h" #include @@ -83,6 +84,9 @@ public: SWGSimplePTTReport* getSimplePttReport(); void setSimplePttReport(SWGSimplePTTReport* simple_ptt_report); + SWGSkyMapReport* getSkyMapReport(); + void setSkyMapReport(SWGSkyMapReport* sky_map_report); + SWGStarTrackerReport* getStarTrackerReport(); void setStarTrackerReport(SWGStarTrackerReport* star_tracker_report); @@ -123,6 +127,9 @@ private: SWGSimplePTTReport* simple_ptt_report; bool m_simple_ptt_report_isSet; + SWGSkyMapReport* sky_map_report; + bool m_sky_map_report_isSet; + SWGStarTrackerReport* star_tracker_report; bool m_star_tracker_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp index 992647cd0..8e007f1ca 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.cpp @@ -62,10 +62,12 @@ SWGFeatureSettings::SWGFeatureSettings() { m_rig_ctl_server_settings_isSet = false; satellite_tracker_settings = nullptr; m_satellite_tracker_settings_isSet = false; - star_tracker_settings = nullptr; - m_star_tracker_settings_isSet = false; simple_ptt_settings = nullptr; m_simple_ptt_settings_isSet = false; + sky_map_settings = nullptr; + m_sky_map_settings_isSet = false; + star_tracker_settings = nullptr; + m_star_tracker_settings_isSet = false; vor_localizer_settings = nullptr; m_vor_localizer_settings_isSet = false; } @@ -110,10 +112,12 @@ SWGFeatureSettings::init() { m_rig_ctl_server_settings_isSet = false; satellite_tracker_settings = new SWGSatelliteTrackerSettings(); m_satellite_tracker_settings_isSet = false; - star_tracker_settings = new SWGStarTrackerSettings(); - m_star_tracker_settings_isSet = false; simple_ptt_settings = new SWGSimplePTTSettings(); m_simple_ptt_settings_isSet = false; + sky_map_settings = new SWGSkyMapSettings(); + m_sky_map_settings_isSet = false; + star_tracker_settings = new SWGStarTrackerSettings(); + m_star_tracker_settings_isSet = false; vor_localizer_settings = new SWGVORLocalizerSettings(); m_vor_localizer_settings_isSet = false; } @@ -167,12 +171,15 @@ SWGFeatureSettings::cleanup() { if(satellite_tracker_settings != nullptr) { delete satellite_tracker_settings; } - if(star_tracker_settings != nullptr) { - delete star_tracker_settings; - } if(simple_ptt_settings != nullptr) { delete simple_ptt_settings; } + if(sky_map_settings != nullptr) { + delete sky_map_settings; + } + if(star_tracker_settings != nullptr) { + delete star_tracker_settings; + } if(vor_localizer_settings != nullptr) { delete vor_localizer_settings; } @@ -223,10 +230,12 @@ SWGFeatureSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&satellite_tracker_settings, pJson["SatelliteTrackerSettings"], "SWGSatelliteTrackerSettings", "SWGSatelliteTrackerSettings"); - ::SWGSDRangel::setValue(&star_tracker_settings, pJson["StarTrackerSettings"], "SWGStarTrackerSettings", "SWGStarTrackerSettings"); - ::SWGSDRangel::setValue(&simple_ptt_settings, pJson["SimplePTTSettings"], "SWGSimplePTTSettings", "SWGSimplePTTSettings"); + ::SWGSDRangel::setValue(&sky_map_settings, pJson["SkyMapSettings"], "SWGSkyMapSettings", "SWGSkyMapSettings"); + + ::SWGSDRangel::setValue(&star_tracker_settings, pJson["StarTrackerSettings"], "SWGStarTrackerSettings", "SWGStarTrackerSettings"); + ::SWGSDRangel::setValue(&vor_localizer_settings, pJson["VORLocalizerSettings"], "SWGVORLocalizerSettings", "SWGVORLocalizerSettings"); } @@ -296,12 +305,15 @@ SWGFeatureSettings::asJsonObject() { if((satellite_tracker_settings != nullptr) && (satellite_tracker_settings->isSet())){ toJsonValue(QString("SatelliteTrackerSettings"), satellite_tracker_settings, obj, QString("SWGSatelliteTrackerSettings")); } - if((star_tracker_settings != nullptr) && (star_tracker_settings->isSet())){ - toJsonValue(QString("StarTrackerSettings"), star_tracker_settings, obj, QString("SWGStarTrackerSettings")); - } if((simple_ptt_settings != nullptr) && (simple_ptt_settings->isSet())){ toJsonValue(QString("SimplePTTSettings"), simple_ptt_settings, obj, QString("SWGSimplePTTSettings")); } + if((sky_map_settings != nullptr) && (sky_map_settings->isSet())){ + toJsonValue(QString("SkyMapSettings"), sky_map_settings, obj, QString("SWGSkyMapSettings")); + } + if((star_tracker_settings != nullptr) && (star_tracker_settings->isSet())){ + toJsonValue(QString("StarTrackerSettings"), star_tracker_settings, obj, QString("SWGStarTrackerSettings")); + } if((vor_localizer_settings != nullptr) && (vor_localizer_settings->isSet())){ toJsonValue(QString("VORLocalizerSettings"), vor_localizer_settings, obj, QString("SWGVORLocalizerSettings")); } @@ -479,16 +491,6 @@ SWGFeatureSettings::setSatelliteTrackerSettings(SWGSatelliteTrackerSettings* sat this->m_satellite_tracker_settings_isSet = true; } -SWGStarTrackerSettings* -SWGFeatureSettings::getStarTrackerSettings() { - return star_tracker_settings; -} -void -SWGFeatureSettings::setStarTrackerSettings(SWGStarTrackerSettings* star_tracker_settings) { - this->star_tracker_settings = star_tracker_settings; - this->m_star_tracker_settings_isSet = true; -} - SWGSimplePTTSettings* SWGFeatureSettings::getSimplePttSettings() { return simple_ptt_settings; @@ -499,6 +501,26 @@ SWGFeatureSettings::setSimplePttSettings(SWGSimplePTTSettings* simple_ptt_settin this->m_simple_ptt_settings_isSet = true; } +SWGSkyMapSettings* +SWGFeatureSettings::getSkyMapSettings() { + return sky_map_settings; +} +void +SWGFeatureSettings::setSkyMapSettings(SWGSkyMapSettings* sky_map_settings) { + this->sky_map_settings = sky_map_settings; + this->m_sky_map_settings_isSet = true; +} + +SWGStarTrackerSettings* +SWGFeatureSettings::getStarTrackerSettings() { + return star_tracker_settings; +} +void +SWGFeatureSettings::setStarTrackerSettings(SWGStarTrackerSettings* star_tracker_settings) { + this->star_tracker_settings = star_tracker_settings; + this->m_star_tracker_settings_isSet = true; +} + SWGVORLocalizerSettings* SWGFeatureSettings::getVorLocalizerSettings() { return vor_localizer_settings; @@ -565,10 +587,13 @@ SWGFeatureSettings::isSet(){ if(satellite_tracker_settings && satellite_tracker_settings->isSet()){ isObjectUpdated = true; break; } - if(star_tracker_settings && star_tracker_settings->isSet()){ + if(simple_ptt_settings && simple_ptt_settings->isSet()){ isObjectUpdated = true; break; } - if(simple_ptt_settings && simple_ptt_settings->isSet()){ + if(sky_map_settings && sky_map_settings->isSet()){ + isObjectUpdated = true; break; + } + if(star_tracker_settings && star_tracker_settings->isSet()){ isObjectUpdated = true; break; } if(vor_localizer_settings && vor_localizer_settings->isSet()){ diff --git a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h index 27b5d305a..9c13ff370 100644 --- a/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGFeatureSettings.h @@ -37,6 +37,7 @@ #include "SWGRigCtlServerSettings.h" #include "SWGSatelliteTrackerSettings.h" #include "SWGSimplePTTSettings.h" +#include "SWGSkyMapSettings.h" #include "SWGStarTrackerSettings.h" #include "SWGVORLocalizerSettings.h" #include @@ -110,12 +111,15 @@ public: SWGSatelliteTrackerSettings* getSatelliteTrackerSettings(); void setSatelliteTrackerSettings(SWGSatelliteTrackerSettings* satellite_tracker_settings); - SWGStarTrackerSettings* getStarTrackerSettings(); - void setStarTrackerSettings(SWGStarTrackerSettings* star_tracker_settings); - SWGSimplePTTSettings* getSimplePttSettings(); void setSimplePttSettings(SWGSimplePTTSettings* simple_ptt_settings); + SWGSkyMapSettings* getSkyMapSettings(); + void setSkyMapSettings(SWGSkyMapSettings* sky_map_settings); + + SWGStarTrackerSettings* getStarTrackerSettings(); + void setStarTrackerSettings(SWGStarTrackerSettings* star_tracker_settings); + SWGVORLocalizerSettings* getVorLocalizerSettings(); void setVorLocalizerSettings(SWGVORLocalizerSettings* vor_localizer_settings); @@ -174,12 +178,15 @@ private: SWGSatelliteTrackerSettings* satellite_tracker_settings; bool m_satellite_tracker_settings_isSet; - SWGStarTrackerSettings* star_tracker_settings; - bool m_star_tracker_settings_isSet; - SWGSimplePTTSettings* simple_ptt_settings; bool m_simple_ptt_settings_isSet; + SWGSkyMapSettings* sky_map_settings; + bool m_sky_map_settings_isSet; + + SWGStarTrackerSettings* star_tracker_settings; + bool m_star_tracker_settings_isSet; + SWGVORLocalizerSettings* vor_localizer_settings; bool m_vor_localizer_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 327be9e8b..0fdf242bc 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -319,6 +319,11 @@ #include "SWGSimplePTTActions.h" #include "SWGSimplePTTReport.h" #include "SWGSimplePTTSettings.h" +#include "SWGSkyMapActions.h" +#include "SWGSkyMapReport.h" +#include "SWGSkyMapSettings.h" +#include "SWGSkyMapTarget.h" +#include "SWGSkyMapTarget_2.h" #include "SWGSoapySDRFrequencySetting.h" #include "SWGSoapySDRGainSetting.h" #include "SWGSoapySDRInputSettings.h" @@ -1900,6 +1905,31 @@ namespace SWGSDRangel { obj->init(); return obj; } + if(QString("SWGSkyMapActions").compare(type) == 0) { + SWGSkyMapActions *obj = new SWGSkyMapActions(); + obj->init(); + return obj; + } + if(QString("SWGSkyMapReport").compare(type) == 0) { + SWGSkyMapReport *obj = new SWGSkyMapReport(); + obj->init(); + return obj; + } + if(QString("SWGSkyMapSettings").compare(type) == 0) { + SWGSkyMapSettings *obj = new SWGSkyMapSettings(); + obj->init(); + return obj; + } + if(QString("SWGSkyMapTarget").compare(type) == 0) { + SWGSkyMapTarget *obj = new SWGSkyMapTarget(); + obj->init(); + return obj; + } + if(QString("SWGSkyMapTarget_2").compare(type) == 0) { + SWGSkyMapTarget_2 *obj = new SWGSkyMapTarget_2(); + obj->init(); + return obj; + } if(QString("SWGSoapySDRFrequencySetting").compare(type) == 0) { SWGSoapySDRFrequencySetting *obj = new SWGSoapySDRFrequencySetting(); obj->init(); diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.cpp b/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.cpp new file mode 100644 index 000000000..979b20df5 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.cpp @@ -0,0 +1,110 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSkyMapActions.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSkyMapActions::SWGSkyMapActions(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSkyMapActions::SWGSkyMapActions() { + find = nullptr; + m_find_isSet = false; +} + +SWGSkyMapActions::~SWGSkyMapActions() { + this->cleanup(); +} + +void +SWGSkyMapActions::init() { + find = new QString(""); + m_find_isSet = false; +} + +void +SWGSkyMapActions::cleanup() { + if(find != nullptr) { + delete find; + } +} + +SWGSkyMapActions* +SWGSkyMapActions::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSkyMapActions::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&find, pJson["find"], "QString", "QString"); + +} + +QString +SWGSkyMapActions::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSkyMapActions::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(find != nullptr && *find != QString("")){ + toJsonValue(QString("find"), find, obj, QString("QString")); + } + + return obj; +} + +QString* +SWGSkyMapActions::getFind() { + return find; +} +void +SWGSkyMapActions::setFind(QString* find) { + this->find = find; + this->m_find_isSet = true; +} + + +bool +SWGSkyMapActions::isSet(){ + bool isObjectUpdated = false; + do{ + if(find && *find != QString("")){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.h b/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.h new file mode 100644 index 000000000..baac9faa0 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapActions.h @@ -0,0 +1,59 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSkyMapActions.h + * + * Sky Map + */ + +#ifndef SWGSkyMapActions_H_ +#define SWGSkyMapActions_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSkyMapActions: public SWGObject { +public: + SWGSkyMapActions(); + SWGSkyMapActions(QString* json); + virtual ~SWGSkyMapActions(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSkyMapActions* fromJson(QString &jsonString) override; + + QString* getFind(); + void setFind(QString* find); + + + virtual bool isSet() override; + +private: + QString* find; + bool m_find_isSet; + +}; + +} + +#endif /* SWGSkyMapActions_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.cpp b/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.cpp new file mode 100644 index 000000000..6d4e5f721 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.cpp @@ -0,0 +1,294 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSkyMapReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSkyMapReport::SWGSkyMapReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSkyMapReport::SWGSkyMapReport() { + date_time = nullptr; + m_date_time_isSet = false; + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + azimuth = 0.0f; + m_azimuth_isSet = false; + elevation = 0.0f; + m_elevation_isSet = false; + fov = 0.0f; + m_fov_isSet = false; +} + +SWGSkyMapReport::~SWGSkyMapReport() { + this->cleanup(); +} + +void +SWGSkyMapReport::init() { + date_time = new QString(""); + m_date_time_isSet = false; + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + azimuth = 0.0f; + m_azimuth_isSet = false; + elevation = 0.0f; + m_elevation_isSet = false; + fov = 0.0f; + m_fov_isSet = false; +} + +void +SWGSkyMapReport::cleanup() { + if(date_time != nullptr) { + delete date_time; + } + + + + + + + + +} + +SWGSkyMapReport* +SWGSkyMapReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSkyMapReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&date_time, pJson["dateTime"], "QString", "QString"); + + ::SWGSDRangel::setValue(&ra, pJson["ra"], "float", ""); + + ::SWGSDRangel::setValue(&dec, pJson["dec"], "float", ""); + + ::SWGSDRangel::setValue(&latitude, pJson["latitude"], "float", ""); + + ::SWGSDRangel::setValue(&longitude, pJson["longitude"], "float", ""); + + ::SWGSDRangel::setValue(&altitude, pJson["altitude"], "float", ""); + + ::SWGSDRangel::setValue(&azimuth, pJson["azimuth"], "float", ""); + + ::SWGSDRangel::setValue(&elevation, pJson["elevation"], "float", ""); + + ::SWGSDRangel::setValue(&fov, pJson["fov"], "float", ""); + +} + +QString +SWGSkyMapReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSkyMapReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(date_time != nullptr && *date_time != QString("")){ + toJsonValue(QString("dateTime"), date_time, obj, QString("QString")); + } + if(m_ra_isSet){ + obj->insert("ra", QJsonValue(ra)); + } + if(m_dec_isSet){ + obj->insert("dec", QJsonValue(dec)); + } + if(m_latitude_isSet){ + obj->insert("latitude", QJsonValue(latitude)); + } + if(m_longitude_isSet){ + obj->insert("longitude", QJsonValue(longitude)); + } + if(m_altitude_isSet){ + obj->insert("altitude", QJsonValue(altitude)); + } + if(m_azimuth_isSet){ + obj->insert("azimuth", QJsonValue(azimuth)); + } + if(m_elevation_isSet){ + obj->insert("elevation", QJsonValue(elevation)); + } + if(m_fov_isSet){ + obj->insert("fov", QJsonValue(fov)); + } + + return obj; +} + +QString* +SWGSkyMapReport::getDateTime() { + return date_time; +} +void +SWGSkyMapReport::setDateTime(QString* date_time) { + this->date_time = date_time; + this->m_date_time_isSet = true; +} + +float +SWGSkyMapReport::getRa() { + return ra; +} +void +SWGSkyMapReport::setRa(float ra) { + this->ra = ra; + this->m_ra_isSet = true; +} + +float +SWGSkyMapReport::getDec() { + return dec; +} +void +SWGSkyMapReport::setDec(float dec) { + this->dec = dec; + this->m_dec_isSet = true; +} + +float +SWGSkyMapReport::getLatitude() { + return latitude; +} +void +SWGSkyMapReport::setLatitude(float latitude) { + this->latitude = latitude; + this->m_latitude_isSet = true; +} + +float +SWGSkyMapReport::getLongitude() { + return longitude; +} +void +SWGSkyMapReport::setLongitude(float longitude) { + this->longitude = longitude; + this->m_longitude_isSet = true; +} + +float +SWGSkyMapReport::getAltitude() { + return altitude; +} +void +SWGSkyMapReport::setAltitude(float altitude) { + this->altitude = altitude; + this->m_altitude_isSet = true; +} + +float +SWGSkyMapReport::getAzimuth() { + return azimuth; +} +void +SWGSkyMapReport::setAzimuth(float azimuth) { + this->azimuth = azimuth; + this->m_azimuth_isSet = true; +} + +float +SWGSkyMapReport::getElevation() { + return elevation; +} +void +SWGSkyMapReport::setElevation(float elevation) { + this->elevation = elevation; + this->m_elevation_isSet = true; +} + +float +SWGSkyMapReport::getFov() { + return fov; +} +void +SWGSkyMapReport::setFov(float fov) { + this->fov = fov; + this->m_fov_isSet = true; +} + + +bool +SWGSkyMapReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(date_time && *date_time != QString("")){ + isObjectUpdated = true; break; + } + if(m_ra_isSet){ + isObjectUpdated = true; break; + } + if(m_dec_isSet){ + isObjectUpdated = true; break; + } + if(m_latitude_isSet){ + isObjectUpdated = true; break; + } + if(m_longitude_isSet){ + isObjectUpdated = true; break; + } + if(m_altitude_isSet){ + isObjectUpdated = true; break; + } + if(m_azimuth_isSet){ + isObjectUpdated = true; break; + } + if(m_elevation_isSet){ + isObjectUpdated = true; break; + } + if(m_fov_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.h b/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.h new file mode 100644 index 000000000..b35e1e1e9 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapReport.h @@ -0,0 +1,107 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSkyMapReport.h + * + * Sky Map + */ + +#ifndef SWGSkyMapReport_H_ +#define SWGSkyMapReport_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSkyMapReport: public SWGObject { +public: + SWGSkyMapReport(); + SWGSkyMapReport(QString* json); + virtual ~SWGSkyMapReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSkyMapReport* fromJson(QString &jsonString) override; + + QString* getDateTime(); + void setDateTime(QString* date_time); + + float getRa(); + void setRa(float ra); + + float getDec(); + void setDec(float dec); + + float getLatitude(); + void setLatitude(float latitude); + + float getLongitude(); + void setLongitude(float longitude); + + float getAltitude(); + void setAltitude(float altitude); + + float getAzimuth(); + void setAzimuth(float azimuth); + + float getElevation(); + void setElevation(float elevation); + + float getFov(); + void setFov(float fov); + + + virtual bool isSet() override; + +private: + QString* date_time; + bool m_date_time_isSet; + + float ra; + bool m_ra_isSet; + + float dec; + bool m_dec_isSet; + + float latitude; + bool m_latitude_isSet; + + float longitude; + bool m_longitude_isSet; + + float altitude; + bool m_altitude_isSet; + + float azimuth; + bool m_azimuth_isSet; + + float elevation; + bool m_elevation_isSet; + + float fov; + bool m_fov_isSet; + +}; + +} + +#endif /* SWGSkyMapReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.cpp new file mode 100644 index 000000000..3ecac528b --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.cpp @@ -0,0 +1,628 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSkyMapSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSkyMapSettings::SWGSkyMapSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSkyMapSettings::SWGSkyMapSettings() { + display_names = 0; + m_display_names_isSet = false; + display_constellations = 0; + m_display_constellations_isSet = false; + display_reticle = 0; + m_display_reticle_isSet = false; + display_grid = 0; + m_display_grid_isSet = false; + display_antenna_fo_v = 0; + m_display_antenna_fo_v_isSet = false; + map = nullptr; + m_map_isSet = false; + background = nullptr; + m_background_isSet = false; + projection = nullptr; + m_projection_isSet = false; + source = nullptr; + m_source_isSet = false; + track = 0; + m_track_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + use_my_position = 0.0f; + m_use_my_position_isSet = false; + title = nullptr; + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_feature_set_index = 0; + m_reverse_api_feature_set_index_isSet = false; + reverse_api_feature_index = 0; + m_reverse_api_feature_index_isSet = false; + rollup_state = nullptr; + m_rollup_state_isSet = false; +} + +SWGSkyMapSettings::~SWGSkyMapSettings() { + this->cleanup(); +} + +void +SWGSkyMapSettings::init() { + display_names = 0; + m_display_names_isSet = false; + display_constellations = 0; + m_display_constellations_isSet = false; + display_reticle = 0; + m_display_reticle_isSet = false; + display_grid = 0; + m_display_grid_isSet = false; + display_antenna_fo_v = 0; + m_display_antenna_fo_v_isSet = false; + map = new QString(""); + m_map_isSet = false; + background = new QString(""); + m_background_isSet = false; + projection = new QString(""); + m_projection_isSet = false; + source = new QString(""); + m_source_isSet = false; + track = 0; + m_track_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + use_my_position = 0.0f; + m_use_my_position_isSet = false; + title = new QString(""); + m_title_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_feature_set_index = 0; + m_reverse_api_feature_set_index_isSet = false; + reverse_api_feature_index = 0; + m_reverse_api_feature_index_isSet = false; + rollup_state = new SWGRollupState(); + m_rollup_state_isSet = false; +} + +void +SWGSkyMapSettings::cleanup() { + + + + + + if(map != nullptr) { + delete map; + } + if(background != nullptr) { + delete background; + } + if(projection != nullptr) { + delete projection; + } + if(source != nullptr) { + delete source; + } + + + + + + + if(title != nullptr) { + delete title; + } + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + + if(rollup_state != nullptr) { + delete rollup_state; + } +} + +SWGSkyMapSettings* +SWGSkyMapSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSkyMapSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&display_names, pJson["displayNames"], "qint32", ""); + + ::SWGSDRangel::setValue(&display_constellations, pJson["displayConstellations"], "qint32", ""); + + ::SWGSDRangel::setValue(&display_reticle, pJson["displayReticle"], "qint32", ""); + + ::SWGSDRangel::setValue(&display_grid, pJson["displayGrid"], "qint32", ""); + + ::SWGSDRangel::setValue(&display_antenna_fo_v, pJson["displayAntennaFoV"], "qint32", ""); + + ::SWGSDRangel::setValue(&map, pJson["map"], "QString", "QString"); + + ::SWGSDRangel::setValue(&background, pJson["background"], "QString", "QString"); + + ::SWGSDRangel::setValue(&projection, pJson["projection"], "QString", "QString"); + + ::SWGSDRangel::setValue(&source, pJson["source"], "QString", "QString"); + + ::SWGSDRangel::setValue(&track, pJson["track"], "qint32", ""); + + ::SWGSDRangel::setValue(&latitude, pJson["latitude"], "float", ""); + + ::SWGSDRangel::setValue(&longitude, pJson["longitude"], "float", ""); + + ::SWGSDRangel::setValue(&altitude, pJson["altitude"], "float", ""); + + ::SWGSDRangel::setValue(&hpbw, pJson["hpbw"], "float", ""); + + ::SWGSDRangel::setValue(&use_my_position, pJson["useMyPosition"], "float", ""); + + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_feature_set_index, pJson["reverseAPIFeatureSetIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_feature_index, pJson["reverseAPIFeatureIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState"); + +} + +QString +SWGSkyMapSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSkyMapSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_display_names_isSet){ + obj->insert("displayNames", QJsonValue(display_names)); + } + if(m_display_constellations_isSet){ + obj->insert("displayConstellations", QJsonValue(display_constellations)); + } + if(m_display_reticle_isSet){ + obj->insert("displayReticle", QJsonValue(display_reticle)); + } + if(m_display_grid_isSet){ + obj->insert("displayGrid", QJsonValue(display_grid)); + } + if(m_display_antenna_fo_v_isSet){ + obj->insert("displayAntennaFoV", QJsonValue(display_antenna_fo_v)); + } + if(map != nullptr && *map != QString("")){ + toJsonValue(QString("map"), map, obj, QString("QString")); + } + if(background != nullptr && *background != QString("")){ + toJsonValue(QString("background"), background, obj, QString("QString")); + } + if(projection != nullptr && *projection != QString("")){ + toJsonValue(QString("projection"), projection, obj, QString("QString")); + } + if(source != nullptr && *source != QString("")){ + toJsonValue(QString("source"), source, obj, QString("QString")); + } + if(m_track_isSet){ + obj->insert("track", QJsonValue(track)); + } + if(m_latitude_isSet){ + obj->insert("latitude", QJsonValue(latitude)); + } + if(m_longitude_isSet){ + obj->insert("longitude", QJsonValue(longitude)); + } + if(m_altitude_isSet){ + obj->insert("altitude", QJsonValue(altitude)); + } + if(m_hpbw_isSet){ + obj->insert("hpbw", QJsonValue(hpbw)); + } + if(m_use_my_position_isSet){ + obj->insert("useMyPosition", QJsonValue(use_my_position)); + } + if(title != nullptr && *title != QString("")){ + toJsonValue(QString("title"), title, obj, QString("QString")); + } + if(m_rgb_color_isSet){ + obj->insert("rgbColor", QJsonValue(rgb_color)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_feature_set_index_isSet){ + obj->insert("reverseAPIFeatureSetIndex", QJsonValue(reverse_api_feature_set_index)); + } + if(m_reverse_api_feature_index_isSet){ + obj->insert("reverseAPIFeatureIndex", QJsonValue(reverse_api_feature_index)); + } + if((rollup_state != nullptr) && (rollup_state->isSet())){ + toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState")); + } + + return obj; +} + +qint32 +SWGSkyMapSettings::getDisplayNames() { + return display_names; +} +void +SWGSkyMapSettings::setDisplayNames(qint32 display_names) { + this->display_names = display_names; + this->m_display_names_isSet = true; +} + +qint32 +SWGSkyMapSettings::getDisplayConstellations() { + return display_constellations; +} +void +SWGSkyMapSettings::setDisplayConstellations(qint32 display_constellations) { + this->display_constellations = display_constellations; + this->m_display_constellations_isSet = true; +} + +qint32 +SWGSkyMapSettings::getDisplayReticle() { + return display_reticle; +} +void +SWGSkyMapSettings::setDisplayReticle(qint32 display_reticle) { + this->display_reticle = display_reticle; + this->m_display_reticle_isSet = true; +} + +qint32 +SWGSkyMapSettings::getDisplayGrid() { + return display_grid; +} +void +SWGSkyMapSettings::setDisplayGrid(qint32 display_grid) { + this->display_grid = display_grid; + this->m_display_grid_isSet = true; +} + +qint32 +SWGSkyMapSettings::getDisplayAntennaFoV() { + return display_antenna_fo_v; +} +void +SWGSkyMapSettings::setDisplayAntennaFoV(qint32 display_antenna_fo_v) { + this->display_antenna_fo_v = display_antenna_fo_v; + this->m_display_antenna_fo_v_isSet = true; +} + +QString* +SWGSkyMapSettings::getMap() { + return map; +} +void +SWGSkyMapSettings::setMap(QString* map) { + this->map = map; + this->m_map_isSet = true; +} + +QString* +SWGSkyMapSettings::getBackground() { + return background; +} +void +SWGSkyMapSettings::setBackground(QString* background) { + this->background = background; + this->m_background_isSet = true; +} + +QString* +SWGSkyMapSettings::getProjection() { + return projection; +} +void +SWGSkyMapSettings::setProjection(QString* projection) { + this->projection = projection; + this->m_projection_isSet = true; +} + +QString* +SWGSkyMapSettings::getSource() { + return source; +} +void +SWGSkyMapSettings::setSource(QString* source) { + this->source = source; + this->m_source_isSet = true; +} + +qint32 +SWGSkyMapSettings::getTrack() { + return track; +} +void +SWGSkyMapSettings::setTrack(qint32 track) { + this->track = track; + this->m_track_isSet = true; +} + +float +SWGSkyMapSettings::getLatitude() { + return latitude; +} +void +SWGSkyMapSettings::setLatitude(float latitude) { + this->latitude = latitude; + this->m_latitude_isSet = true; +} + +float +SWGSkyMapSettings::getLongitude() { + return longitude; +} +void +SWGSkyMapSettings::setLongitude(float longitude) { + this->longitude = longitude; + this->m_longitude_isSet = true; +} + +float +SWGSkyMapSettings::getAltitude() { + return altitude; +} +void +SWGSkyMapSettings::setAltitude(float altitude) { + this->altitude = altitude; + this->m_altitude_isSet = true; +} + +float +SWGSkyMapSettings::getHpbw() { + return hpbw; +} +void +SWGSkyMapSettings::setHpbw(float hpbw) { + this->hpbw = hpbw; + this->m_hpbw_isSet = true; +} + +float +SWGSkyMapSettings::getUseMyPosition() { + return use_my_position; +} +void +SWGSkyMapSettings::setUseMyPosition(float use_my_position) { + this->use_my_position = use_my_position; + this->m_use_my_position_isSet = true; +} + +QString* +SWGSkyMapSettings::getTitle() { + return title; +} +void +SWGSkyMapSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGSkyMapSettings::getRgbColor() { + return rgb_color; +} +void +SWGSkyMapSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +qint32 +SWGSkyMapSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGSkyMapSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGSkyMapSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGSkyMapSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGSkyMapSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGSkyMapSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGSkyMapSettings::getReverseApiFeatureSetIndex() { + return reverse_api_feature_set_index; +} +void +SWGSkyMapSettings::setReverseApiFeatureSetIndex(qint32 reverse_api_feature_set_index) { + this->reverse_api_feature_set_index = reverse_api_feature_set_index; + this->m_reverse_api_feature_set_index_isSet = true; +} + +qint32 +SWGSkyMapSettings::getReverseApiFeatureIndex() { + return reverse_api_feature_index; +} +void +SWGSkyMapSettings::setReverseApiFeatureIndex(qint32 reverse_api_feature_index) { + this->reverse_api_feature_index = reverse_api_feature_index; + this->m_reverse_api_feature_index_isSet = true; +} + +SWGRollupState* +SWGSkyMapSettings::getRollupState() { + return rollup_state; +} +void +SWGSkyMapSettings::setRollupState(SWGRollupState* rollup_state) { + this->rollup_state = rollup_state; + this->m_rollup_state_isSet = true; +} + + +bool +SWGSkyMapSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_display_names_isSet){ + isObjectUpdated = true; break; + } + if(m_display_constellations_isSet){ + isObjectUpdated = true; break; + } + if(m_display_reticle_isSet){ + isObjectUpdated = true; break; + } + if(m_display_grid_isSet){ + isObjectUpdated = true; break; + } + if(m_display_antenna_fo_v_isSet){ + isObjectUpdated = true; break; + } + if(map && *map != QString("")){ + isObjectUpdated = true; break; + } + if(background && *background != QString("")){ + isObjectUpdated = true; break; + } + if(projection && *projection != QString("")){ + isObjectUpdated = true; break; + } + if(source && *source != QString("")){ + isObjectUpdated = true; break; + } + if(m_track_isSet){ + isObjectUpdated = true; break; + } + if(m_latitude_isSet){ + isObjectUpdated = true; break; + } + if(m_longitude_isSet){ + isObjectUpdated = true; break; + } + if(m_altitude_isSet){ + isObjectUpdated = true; break; + } + if(m_hpbw_isSet){ + isObjectUpdated = true; break; + } + if(m_use_my_position_isSet){ + isObjectUpdated = true; break; + } + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_feature_set_index_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_feature_index_isSet){ + isObjectUpdated = true; break; + } + if(rollup_state && rollup_state->isSet()){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.h b/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.h new file mode 100644 index 000000000..325068ea2 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapSettings.h @@ -0,0 +1,192 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSkyMapSettings.h + * + * Sky Map + */ + +#ifndef SWGSkyMapSettings_H_ +#define SWGSkyMapSettings_H_ + +#include + + +#include "SWGRollupState.h" +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSkyMapSettings: public SWGObject { +public: + SWGSkyMapSettings(); + SWGSkyMapSettings(QString* json); + virtual ~SWGSkyMapSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSkyMapSettings* fromJson(QString &jsonString) override; + + qint32 getDisplayNames(); + void setDisplayNames(qint32 display_names); + + qint32 getDisplayConstellations(); + void setDisplayConstellations(qint32 display_constellations); + + qint32 getDisplayReticle(); + void setDisplayReticle(qint32 display_reticle); + + qint32 getDisplayGrid(); + void setDisplayGrid(qint32 display_grid); + + qint32 getDisplayAntennaFoV(); + void setDisplayAntennaFoV(qint32 display_antenna_fo_v); + + QString* getMap(); + void setMap(QString* map); + + QString* getBackground(); + void setBackground(QString* background); + + QString* getProjection(); + void setProjection(QString* projection); + + QString* getSource(); + void setSource(QString* source); + + qint32 getTrack(); + void setTrack(qint32 track); + + float getLatitude(); + void setLatitude(float latitude); + + float getLongitude(); + void setLongitude(float longitude); + + float getAltitude(); + void setAltitude(float altitude); + + float getHpbw(); + void setHpbw(float hpbw); + + float getUseMyPosition(); + void setUseMyPosition(float use_my_position); + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiFeatureSetIndex(); + void setReverseApiFeatureSetIndex(qint32 reverse_api_feature_set_index); + + qint32 getReverseApiFeatureIndex(); + void setReverseApiFeatureIndex(qint32 reverse_api_feature_index); + + SWGRollupState* getRollupState(); + void setRollupState(SWGRollupState* rollup_state); + + + virtual bool isSet() override; + +private: + qint32 display_names; + bool m_display_names_isSet; + + qint32 display_constellations; + bool m_display_constellations_isSet; + + qint32 display_reticle; + bool m_display_reticle_isSet; + + qint32 display_grid; + bool m_display_grid_isSet; + + qint32 display_antenna_fo_v; + bool m_display_antenna_fo_v_isSet; + + QString* map; + bool m_map_isSet; + + QString* background; + bool m_background_isSet; + + QString* projection; + bool m_projection_isSet; + + QString* source; + bool m_source_isSet; + + qint32 track; + bool m_track_isSet; + + float latitude; + bool m_latitude_isSet; + + float longitude; + bool m_longitude_isSet; + + float altitude; + bool m_altitude_isSet; + + float hpbw; + bool m_hpbw_isSet; + + float use_my_position; + bool m_use_my_position_isSet; + + QString* title; + bool m_title_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_feature_set_index; + bool m_reverse_api_feature_set_index_isSet; + + qint32 reverse_api_feature_index; + bool m_reverse_api_feature_index_isSet; + + SWGRollupState* rollup_state; + bool m_rollup_state_isSet; + +}; + +} + +#endif /* SWGSkyMapSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.cpp b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.cpp new file mode 100644 index 000000000..5397fb31f --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.cpp @@ -0,0 +1,248 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSkyMapTarget.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSkyMapTarget::SWGSkyMapTarget(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSkyMapTarget::SWGSkyMapTarget() { + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + date_time = nullptr; + m_date_time_isSet = false; +} + +SWGSkyMapTarget::~SWGSkyMapTarget() { + this->cleanup(); +} + +void +SWGSkyMapTarget::init() { + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + date_time = new QString(""); + m_date_time_isSet = false; +} + +void +SWGSkyMapTarget::cleanup() { + + + + + + + if(date_time != nullptr) { + delete date_time; + } +} + +SWGSkyMapTarget* +SWGSkyMapTarget::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSkyMapTarget::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&ra, pJson["ra"], "float", ""); + + ::SWGSDRangel::setValue(&dec, pJson["dec"], "float", ""); + + ::SWGSDRangel::setValue(&latitude, pJson["latitude"], "float", ""); + + ::SWGSDRangel::setValue(&longitude, pJson["longitude"], "float", ""); + + ::SWGSDRangel::setValue(&altitude, pJson["altitude"], "float", ""); + + ::SWGSDRangel::setValue(&hpbw, pJson["hpbw"], "float", ""); + + ::SWGSDRangel::setValue(&date_time, pJson["dateTime"], "QString", "QString"); + +} + +QString +SWGSkyMapTarget::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSkyMapTarget::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_ra_isSet){ + obj->insert("ra", QJsonValue(ra)); + } + if(m_dec_isSet){ + obj->insert("dec", QJsonValue(dec)); + } + if(m_latitude_isSet){ + obj->insert("latitude", QJsonValue(latitude)); + } + if(m_longitude_isSet){ + obj->insert("longitude", QJsonValue(longitude)); + } + if(m_altitude_isSet){ + obj->insert("altitude", QJsonValue(altitude)); + } + if(m_hpbw_isSet){ + obj->insert("hpbw", QJsonValue(hpbw)); + } + if(date_time != nullptr && *date_time != QString("")){ + toJsonValue(QString("dateTime"), date_time, obj, QString("QString")); + } + + return obj; +} + +float +SWGSkyMapTarget::getRa() { + return ra; +} +void +SWGSkyMapTarget::setRa(float ra) { + this->ra = ra; + this->m_ra_isSet = true; +} + +float +SWGSkyMapTarget::getDec() { + return dec; +} +void +SWGSkyMapTarget::setDec(float dec) { + this->dec = dec; + this->m_dec_isSet = true; +} + +float +SWGSkyMapTarget::getLatitude() { + return latitude; +} +void +SWGSkyMapTarget::setLatitude(float latitude) { + this->latitude = latitude; + this->m_latitude_isSet = true; +} + +float +SWGSkyMapTarget::getLongitude() { + return longitude; +} +void +SWGSkyMapTarget::setLongitude(float longitude) { + this->longitude = longitude; + this->m_longitude_isSet = true; +} + +float +SWGSkyMapTarget::getAltitude() { + return altitude; +} +void +SWGSkyMapTarget::setAltitude(float altitude) { + this->altitude = altitude; + this->m_altitude_isSet = true; +} + +float +SWGSkyMapTarget::getHpbw() { + return hpbw; +} +void +SWGSkyMapTarget::setHpbw(float hpbw) { + this->hpbw = hpbw; + this->m_hpbw_isSet = true; +} + +QString* +SWGSkyMapTarget::getDateTime() { + return date_time; +} +void +SWGSkyMapTarget::setDateTime(QString* date_time) { + this->date_time = date_time; + this->m_date_time_isSet = true; +} + + +bool +SWGSkyMapTarget::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_ra_isSet){ + isObjectUpdated = true; break; + } + if(m_dec_isSet){ + isObjectUpdated = true; break; + } + if(m_latitude_isSet){ + isObjectUpdated = true; break; + } + if(m_longitude_isSet){ + isObjectUpdated = true; break; + } + if(m_altitude_isSet){ + isObjectUpdated = true; break; + } + if(m_hpbw_isSet){ + isObjectUpdated = true; break; + } + if(date_time && *date_time != QString("")){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.h b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.h new file mode 100644 index 000000000..77acd8657 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget.h @@ -0,0 +1,95 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSkyMapTarget.h + * + * Sky Map target. Sent by other plugins to skymap.target message queue. + */ + +#ifndef SWGSkyMapTarget_H_ +#define SWGSkyMapTarget_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSkyMapTarget: public SWGObject { +public: + SWGSkyMapTarget(); + SWGSkyMapTarget(QString* json); + virtual ~SWGSkyMapTarget(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSkyMapTarget* fromJson(QString &jsonString) override; + + float getRa(); + void setRa(float ra); + + float getDec(); + void setDec(float dec); + + float getLatitude(); + void setLatitude(float latitude); + + float getLongitude(); + void setLongitude(float longitude); + + float getAltitude(); + void setAltitude(float altitude); + + float getHpbw(); + void setHpbw(float hpbw); + + QString* getDateTime(); + void setDateTime(QString* date_time); + + + virtual bool isSet() override; + +private: + float ra; + bool m_ra_isSet; + + float dec; + bool m_dec_isSet; + + float latitude; + bool m_latitude_isSet; + + float longitude; + bool m_longitude_isSet; + + float altitude; + bool m_altitude_isSet; + + float hpbw; + bool m_hpbw_isSet; + + QString* date_time; + bool m_date_time_isSet; + +}; + +} + +#endif /* SWGSkyMapTarget_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.cpp b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.cpp new file mode 100644 index 000000000..0371c3cb8 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.cpp @@ -0,0 +1,248 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSkyMapTarget_2.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSkyMapTarget_2::SWGSkyMapTarget_2(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSkyMapTarget_2::SWGSkyMapTarget_2() { + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + date_time = nullptr; + m_date_time_isSet = false; +} + +SWGSkyMapTarget_2::~SWGSkyMapTarget_2() { + this->cleanup(); +} + +void +SWGSkyMapTarget_2::init() { + ra = 0.0f; + m_ra_isSet = false; + dec = 0.0f; + m_dec_isSet = false; + latitude = 0.0f; + m_latitude_isSet = false; + longitude = 0.0f; + m_longitude_isSet = false; + altitude = 0.0f; + m_altitude_isSet = false; + hpbw = 0.0f; + m_hpbw_isSet = false; + date_time = new QString(""); + m_date_time_isSet = false; +} + +void +SWGSkyMapTarget_2::cleanup() { + + + + + + + if(date_time != nullptr) { + delete date_time; + } +} + +SWGSkyMapTarget_2* +SWGSkyMapTarget_2::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSkyMapTarget_2::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&ra, pJson["ra"], "float", ""); + + ::SWGSDRangel::setValue(&dec, pJson["dec"], "float", ""); + + ::SWGSDRangel::setValue(&latitude, pJson["latitude"], "float", ""); + + ::SWGSDRangel::setValue(&longitude, pJson["longitude"], "float", ""); + + ::SWGSDRangel::setValue(&altitude, pJson["altitude"], "float", ""); + + ::SWGSDRangel::setValue(&hpbw, pJson["hpbw"], "float", ""); + + ::SWGSDRangel::setValue(&date_time, pJson["dateTime"], "QString", "QString"); + +} + +QString +SWGSkyMapTarget_2::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSkyMapTarget_2::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_ra_isSet){ + obj->insert("ra", QJsonValue(ra)); + } + if(m_dec_isSet){ + obj->insert("dec", QJsonValue(dec)); + } + if(m_latitude_isSet){ + obj->insert("latitude", QJsonValue(latitude)); + } + if(m_longitude_isSet){ + obj->insert("longitude", QJsonValue(longitude)); + } + if(m_altitude_isSet){ + obj->insert("altitude", QJsonValue(altitude)); + } + if(m_hpbw_isSet){ + obj->insert("hpbw", QJsonValue(hpbw)); + } + if(date_time != nullptr && *date_time != QString("")){ + toJsonValue(QString("dateTime"), date_time, obj, QString("QString")); + } + + return obj; +} + +float +SWGSkyMapTarget_2::getRa() { + return ra; +} +void +SWGSkyMapTarget_2::setRa(float ra) { + this->ra = ra; + this->m_ra_isSet = true; +} + +float +SWGSkyMapTarget_2::getDec() { + return dec; +} +void +SWGSkyMapTarget_2::setDec(float dec) { + this->dec = dec; + this->m_dec_isSet = true; +} + +float +SWGSkyMapTarget_2::getLatitude() { + return latitude; +} +void +SWGSkyMapTarget_2::setLatitude(float latitude) { + this->latitude = latitude; + this->m_latitude_isSet = true; +} + +float +SWGSkyMapTarget_2::getLongitude() { + return longitude; +} +void +SWGSkyMapTarget_2::setLongitude(float longitude) { + this->longitude = longitude; + this->m_longitude_isSet = true; +} + +float +SWGSkyMapTarget_2::getAltitude() { + return altitude; +} +void +SWGSkyMapTarget_2::setAltitude(float altitude) { + this->altitude = altitude; + this->m_altitude_isSet = true; +} + +float +SWGSkyMapTarget_2::getHpbw() { + return hpbw; +} +void +SWGSkyMapTarget_2::setHpbw(float hpbw) { + this->hpbw = hpbw; + this->m_hpbw_isSet = true; +} + +QString* +SWGSkyMapTarget_2::getDateTime() { + return date_time; +} +void +SWGSkyMapTarget_2::setDateTime(QString* date_time) { + this->date_time = date_time; + this->m_date_time_isSet = true; +} + + +bool +SWGSkyMapTarget_2::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_ra_isSet){ + isObjectUpdated = true; break; + } + if(m_dec_isSet){ + isObjectUpdated = true; break; + } + if(m_latitude_isSet){ + isObjectUpdated = true; break; + } + if(m_longitude_isSet){ + isObjectUpdated = true; break; + } + if(m_altitude_isSet){ + isObjectUpdated = true; break; + } + if(m_hpbw_isSet){ + isObjectUpdated = true; break; + } + if(date_time && *date_time != QString("")){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.h b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.h new file mode 100644 index 000000000..ce0b0ca93 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSkyMapTarget_2.h @@ -0,0 +1,95 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 7.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSkyMapTarget_2.h + * + * Sky Map target. Sent by other plugins to skymap.target message queue. + */ + +#ifndef SWGSkyMapTarget_2_H_ +#define SWGSkyMapTarget_2_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSkyMapTarget_2: public SWGObject { +public: + SWGSkyMapTarget_2(); + SWGSkyMapTarget_2(QString* json); + virtual ~SWGSkyMapTarget_2(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSkyMapTarget_2* fromJson(QString &jsonString) override; + + float getRa(); + void setRa(float ra); + + float getDec(); + void setDec(float dec); + + float getLatitude(); + void setLatitude(float latitude); + + float getLongitude(); + void setLongitude(float longitude); + + float getAltitude(); + void setAltitude(float altitude); + + float getHpbw(); + void setHpbw(float hpbw); + + QString* getDateTime(); + void setDateTime(QString* date_time); + + + virtual bool isSet() override; + +private: + float ra; + bool m_ra_isSet; + + float dec; + bool m_dec_isSet; + + float latitude; + bool m_latitude_isSet; + + float longitude; + bool m_longitude_isSet; + + float altitude; + bool m_altitude_isSet; + + float hpbw; + bool m_hpbw_isSet; + + QString* date_time; + bool m_date_time_isSet; + +}; + +} + +#endif /* SWGSkyMapTarget_2_H_ */