diff --git a/doc/img/GS232Controller_plugin.png b/doc/img/GS232Controller_plugin.png index a67064ab4..9dcef6887 100644 Binary files a/doc/img/GS232Controller_plugin.png and b/doc/img/GS232Controller_plugin.png differ diff --git a/doc/img/GS232Controller_plugin.xcf b/doc/img/GS232Controller_plugin.xcf index 01cb5a5a5..3d3b2b299 100644 Binary files a/doc/img/GS232Controller_plugin.xcf and b/doc/img/GS232Controller_plugin.xcf differ diff --git a/plugins/feature/gs232controller/gs232controller.cpp b/plugins/feature/gs232controller/gs232controller.cpp index 6efc567f2..57e182e81 100644 --- a/plugins/feature/gs232controller/gs232controller.cpp +++ b/plugins/feature/gs232controller/gs232controller.cpp @@ -20,33 +20,42 @@ #include #include #include +#include #include "SWGFeatureSettings.h" #include "SWGFeatureReport.h" #include "SWGFeatureActions.h" -#include "SWGSimplePTTReport.h" #include "SWGDeviceState.h" +#include "SWGTargetAzimuthElevation.h" #include "dsp/dspengine.h" +#include "device/deviceset.h" +#include "channel/channelapi.h" +#include "feature/featureset.h" +#include "maincore.h" -#include "gs232controllerworker.h" #include "gs232controller.h" +#include "gs232controllerworker.h" +#include "gs232controllerreport.h" MESSAGE_CLASS_DEFINITION(GS232Controller::MsgConfigureGS232Controller, Message) MESSAGE_CLASS_DEFINITION(GS232Controller::MsgStartStop, Message) +MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportWorker, Message) const char* const GS232Controller::m_featureIdURI = "sdrangel.feature.gs232controller"; const char* const GS232Controller::m_featureId = "GS232Controller"; GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) : - Feature(m_featureIdURI, webAPIAdapterInterface), - m_ptt(false) + Feature(m_featureIdURI, webAPIAdapterInterface) { qDebug("GS232Controller::GS232Controller: webAPIAdapterInterface: %p", webAPIAdapterInterface); setObjectName(m_featureId); - m_worker = new GS232ControllerWorker(webAPIAdapterInterface); + m_worker = new GS232ControllerWorker(); m_state = StIdle; m_errorMessage = "GS232Controller error"; + m_selectedPipe = nullptr; + connect(&m_updatePipesTimer, SIGNAL(timeout()), this, SLOT(updatePipes())); + m_updatePipesTimer.start(1000); } GS232Controller::~GS232Controller() @@ -105,21 +114,46 @@ bool GS232Controller::handleMessage(const Message& cmd) return true; } - else if (GS232ControllerSettings::MsgChannelIndexChange::match(cmd)) + else if (MsgReportWorker::match(cmd)) { - GS232ControllerSettings::MsgChannelIndexChange& cfg = (GS232ControllerSettings::MsgChannelIndexChange&) cmd; - int newChannelIndex = cfg.getIndex(); - qDebug() << "GS232Controller::handleMessage: MsgChannelIndexChange: " << newChannelIndex; - GS232ControllerSettings settings = m_settings; - settings.m_channelIndex = newChannelIndex; - applySettings(settings, false); - - if (getMessageQueueToGUI()) + MsgReportWorker& report = (MsgReportWorker&) cmd; + if (report.getMessage() == "Connected") + m_state = StRunning; + else if (report.getMessage() == "Disconnected") + m_state = StIdle; + else { - GS232ControllerSettings::MsgChannelIndexChange *msg = new GS232ControllerSettings::MsgChannelIndexChange(cfg); - getMessageQueueToGUI()->push(msg); + m_state = StError; + m_errorMessage = report.getMessage(); + } + return true; + } + else if (MainCore::MsgTargetAzimuthElevation::match(cmd)) + { + // New target from another plugin + if ((m_state == StRunning) && m_settings.m_track) + { + MainCore::MsgTargetAzimuthElevation& msg = (MainCore::MsgTargetAzimuthElevation&) cmd; + // Is it from the selected pipe? + if (msg.getPipeSource() == m_selectedPipe) + { + if (getMessageQueueToGUI()) + { + // Forward to GUI - which will then send us updated settings + getMessageQueueToGUI()->push(new MainCore::MsgTargetAzimuthElevation(msg)); + } + else + { + // No GUI, so save target - applySettings will propagate to worker + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = msg.getSWGTargetAzimuthElevation(); + m_settings.m_azimuth = swgTarget->getAzimuth(); + m_settings.m_elevation = swgTarget->getElevation(); + applySettings(m_settings); + } + } + else + qDebug() << "GS232Controller::handleMessage: No match " << msg.getPipeSource() << " " << m_selectedPipe; } - return true; } else @@ -128,6 +162,23 @@ bool GS232Controller::handleMessage(const Message& cmd) } } +void GS232Controller::updatePipes() +{ + QList availablePipes = updateAvailablePipeSources("target", GS232ControllerSettings::m_pipeTypes, GS232ControllerSettings::m_pipeURIs, this); + + if (availablePipes != m_availablePipes) + { + m_availablePipes = availablePipes; + if (getMessageQueueToGUI()) + { + MsgReportPipes *msgToGUI = MsgReportPipes::create(); + QList& msgAvailablePipes = msgToGUI->getAvailablePipes(); + msgAvailablePipes.append(availablePipes); + getMessageQueueToGUI()->push(msgToGUI); + } + } +} + QByteArray GS232Controller::serialize() const { return m_settings.serialize(); @@ -158,8 +209,7 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, boo << " m_serialPort: " << settings.m_serialPort << " m_baudRate: " << settings.m_baudRate << " m_track: " << settings.m_track - << " m_deviceIndex: " << settings.m_deviceIndex - << " m_channelIndex: " << settings.m_channelIndex + << " m_target: " << settings.m_target << " m_title: " << settings.m_title << " m_rgbColor: " << settings.m_rgbColor << " m_useReverseAPI: " << settings.m_useReverseAPI @@ -186,11 +236,24 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, boo if ((m_settings.m_track != settings.m_track) || force) { reverseAPIKeys.append("track"); } - if ((m_settings.m_deviceIndex != settings.m_deviceIndex) || force) { - reverseAPIKeys.append("deviceIndex"); + if ((m_settings.m_target != settings.m_target) + || (!settings.m_target.isEmpty() && (m_selectedPipe == nullptr)) // Change in available pipes + || force) + { + if (!settings.m_target.isEmpty()) + { + m_selectedPipe = getPipeEndPoint(settings.m_target, m_availablePipes); + if (m_selectedPipe == nullptr) + qDebug() << "GS232Controller::applySettings: No plugin corresponding to target " << settings.m_target; + } + + reverseAPIKeys.append("target"); } - if ((m_settings.m_channelIndex != settings.m_channelIndex) || force) { - reverseAPIKeys.append("channelIndex"); + if ((m_settings.m_azimuthOffset != settings.m_azimuthOffset) || force) { + reverseAPIKeys.append("azimuthOffset"); + } + if ((m_settings.m_elevationOffset != settings.m_elevationOffset) || force) { + reverseAPIKeys.append("elevationOffset"); } if ((m_settings.m_title != settings.m_title) || force) { reverseAPIKeys.append("title"); @@ -252,7 +315,6 @@ int GS232Controller::webapiSettingsPutPatch( MsgConfigureGS232Controller *msg = MsgConfigureGS232Controller::create(settings, force); m_inputMessageQueue.push(msg); - qDebug("GS232Controller::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue); if (m_guiMessageQueue) // forward to GUI if any { MsgConfigureGS232Controller *msgToGUI = MsgConfigureGS232Controller::create(settings, force); @@ -273,8 +335,8 @@ void GS232Controller::webapiFormatFeatureSettings( response.getGs232ControllerSettings()->setSerialPort(new QString(settings.m_serialPort)); response.getGs232ControllerSettings()->setBaudRate(settings.m_baudRate); response.getGs232ControllerSettings()->setTrack(settings.m_track); - response.getGs232ControllerSettings()->setDeviceIndex(settings.m_deviceIndex); - response.getGs232ControllerSettings()->setChannelIndex(settings.m_channelIndex); + response.getGs232ControllerSettings()->setAzimuthOffset(settings.m_azimuthOffset); + response.getGs232ControllerSettings()->setElevationOffset(settings.m_elevationOffset); if (response.getGs232ControllerSettings()->getTitle()) { *response.getGs232ControllerSettings()->getTitle() = settings.m_title; @@ -292,8 +354,6 @@ void GS232Controller::webapiFormatFeatureSettings( } response.getGs232ControllerSettings()->setReverseApiPort(settings.m_reverseAPIPort); - response.getGs232ControllerSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIFeatureSetIndex); - response.getGs232ControllerSettings()->setReverseApiChannelIndex(settings.m_reverseAPIFeatureIndex); } void GS232Controller::webapiUpdateFeatureSettings( @@ -316,11 +376,14 @@ void GS232Controller::webapiUpdateFeatureSettings( if (featureSettingsKeys.contains("track")) { settings.m_track = response.getGs232ControllerSettings()->getTrack() != 0; } - if (featureSettingsKeys.contains("deviceIndex")) { - settings.m_deviceIndex = response.getGs232ControllerSettings()->getDeviceIndex(); + if (featureSettingsKeys.contains("target")) { + settings.m_target = *response.getGs232ControllerSettings()->getTarget(); } - if (featureSettingsKeys.contains("channelIndex")) { - settings.m_channelIndex = response.getGs232ControllerSettings()->getChannelIndex(); + if (featureSettingsKeys.contains("azimuthOffset")) { + settings.m_azimuthOffset = response.getGs232ControllerSettings()->getAzimuthOffset(); + } + if (featureSettingsKeys.contains("elevationOffset")) { + settings.m_elevationOffset = response.getGs232ControllerSettings()->getElevationOffset(); } if (featureSettingsKeys.contains("title")) { settings.m_title = *response.getGs232ControllerSettings()->getTitle(); @@ -337,12 +400,6 @@ void GS232Controller::webapiUpdateFeatureSettings( if (featureSettingsKeys.contains("reverseAPIPort")) { settings.m_reverseAPIPort = response.getGs232ControllerSettings()->getReverseApiPort(); } - if (featureSettingsKeys.contains("reverseAPIDeviceIndex")) { - settings.m_reverseAPIFeatureSetIndex = response.getGs232ControllerSettings()->getReverseApiDeviceIndex(); - } - if (featureSettingsKeys.contains("reverseAPIChannelIndex")) { - settings.m_reverseAPIFeatureIndex = response.getGs232ControllerSettings()->getReverseApiChannelIndex(); - } } void GS232Controller::webapiReverseSendSettings(QList& featureSettingsKeys, const GS232ControllerSettings& settings, bool force) @@ -371,11 +428,14 @@ void GS232Controller::webapiReverseSendSettings(QList& featureSettingsK if (featureSettingsKeys.contains("track") || force) { swgGS232ControllerSettings->setTrack(settings.m_track); } - if (featureSettingsKeys.contains("deviceIndex") || force) { - swgGS232ControllerSettings->setDeviceIndex(settings.m_deviceIndex); + if (featureSettingsKeys.contains("target") || force) { + swgGS232ControllerSettings->setTarget(new QString(settings.m_target)); } - if (featureSettingsKeys.contains("channelIndex") || force) { - swgGS232ControllerSettings->setChannelIndex(settings.m_channelIndex); + if (featureSettingsKeys.contains("azimuthOffset") || force) { + swgGS232ControllerSettings->setAzimuthOffset(settings.m_azimuthOffset); + } + if (featureSettingsKeys.contains("elevationOffset") || force) { + swgGS232ControllerSettings->setElevationOffset(settings.m_elevationOffset); } if (featureSettingsKeys.contains("title") || force) { swgGS232ControllerSettings->setTitle(new QString(settings.m_title)); diff --git a/plugins/feature/gs232controller/gs232controller.h b/plugins/feature/gs232controller/gs232controller.h index 124b5942b..3d2c9b811 100644 --- a/plugins/feature/gs232controller/gs232controller.h +++ b/plugins/feature/gs232controller/gs232controller.h @@ -21,6 +21,7 @@ #include #include +#include #include "feature/feature.h" #include "util/message.h" @@ -81,6 +82,25 @@ public: { } }; + class MsgReportWorker : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QString getMessage() { return m_message; } + + static MsgReportWorker* create(QString message) { + return new MsgReportWorker(message); + } + + private: + QString m_message; + + MsgReportWorker(QString message) : + Message(), + m_message(message) + {} + }; + GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface); virtual ~GS232Controller(); virtual void destroy() { delete this; } @@ -122,7 +142,10 @@ private: QThread m_thread; GS232ControllerWorker *m_worker; GS232ControllerSettings m_settings; - bool m_ptt; + //QHash m_availablePipes; + QList m_availablePipes; + PipeEndPoint *m_selectedPipe; + QTimer m_updatePipesTimer; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -133,7 +156,9 @@ private: void webapiReverseSendSettings(QList& featureSettingsKeys, const GS232ControllerSettings& settings, bool force); private slots: + void updatePipes(); void networkManagerFinished(QNetworkReply *reply); + //void handlePipeMessageQueue(MessageQueue* messageQueue); }; #endif // INCLUDE_FEATURE_GS232CONTROLLER_H_ diff --git a/plugins/feature/gs232controller/gs232controllergui.cpp b/plugins/feature/gs232controller/gs232controllergui.cpp index 6d2e3abad..9ed62c6f0 100644 --- a/plugins/feature/gs232controller/gs232controllergui.cpp +++ b/plugins/feature/gs232controller/gs232controllergui.cpp @@ -21,6 +21,8 @@ #include #include +#include "SWGTargetAzimuthElevation.h" + #include "feature/featureuiset.h" #include "gui/basicfeaturesettingsdialog.h" #include "mainwindow.h" @@ -51,7 +53,6 @@ void GS232ControllerGUI::resetToDefaults() QByteArray GS232ControllerGUI::serialize() const { - qDebug("GS232ControllerGUI::serialize: %d", m_settings.m_channelIndex); return m_settings.serialize(); } @@ -59,8 +60,6 @@ bool GS232ControllerGUI::deserialize(const QByteArray& data) { if (m_settings.deserialize(data)) { - qDebug("GS232ControllerGUI::deserialize: %d", m_settings.m_channelIndex); - updateDeviceSetList(); displaySettings(); applySettings(true); return true; @@ -85,30 +84,28 @@ bool GS232ControllerGUI::handleMessage(const Message& message) return true; } - else if (GS232ControllerSettings::MsgChannelIndexChange::match(message)) + else if (PipeEndPoint::MsgReportPipes::match(message)) { - const GS232ControllerSettings::MsgChannelIndexChange& cfg = (GS232ControllerSettings::MsgChannelIndexChange&) message; - int newChannelIndex = cfg.getIndex(); - qDebug("GS232ControllerGUI::handleMessage: GS232ControllerSettings::MsgChannelIndexChange: %d", newChannelIndex); - ui->channel->blockSignals(true); - ui->channel->setCurrentIndex(newChannelIndex); - m_settings.m_channelIndex = newChannelIndex; - ui->channel->blockSignals(false); - + PipeEndPoint::MsgReportPipes& report = (PipeEndPoint::MsgReportPipes&) message; + m_availablePipes = report.getAvailablePipes(); + updatePipeList(); return true; - } else if (GS232ControllerReport::MsgReportAzAl::match(message)) + } + else if (GS232ControllerReport::MsgReportAzAl::match(message)) { GS232ControllerReport::MsgReportAzAl& azAl = (GS232ControllerReport::MsgReportAzAl&) message; - if (azAl.getType() == GS232ControllerReport::AzAlType::TARGET) - { - ui->azimuth->setValue(round(azAl.getAzimuth())); - ui->elevation->setValue(round(azAl.getElevation())); - } - else - { - ui->azimuthCurrentText->setText(QString("%1").arg(round(azAl.getAzimuth()))); - ui->elevationCurrentText->setText(QString("%1").arg(round(azAl.getElevation()))); - } + ui->azimuthCurrentText->setText(QString("%1").arg(round(azAl.getAzimuth()))); + ui->elevationCurrentText->setText(QString("%1").arg(round(azAl.getElevation()))); + return true; + } + else if (MainCore::MsgTargetAzimuthElevation::match(message)) + { + MainCore::MsgTargetAzimuthElevation& msg = (MainCore::MsgTargetAzimuthElevation&) message; + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = msg.getSWGTargetAzimuthElevation(); + + ui->azimuth->setValue(round(swgTarget->getAzimuth())); + ui->elevation->setValue(round(swgTarget->getElevation())); + ui->targetName->setText(*swgTarget->getName()); return true; } @@ -157,7 +154,6 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu m_statusTimer.start(1000); updateSerialPortList(); - updateDeviceSetList(); displaySettings(); applySettings(true); } @@ -183,6 +179,9 @@ void GS232ControllerGUI::displaySettings() ui->serialPort->lineEdit()->setText(m_settings.m_serialPort); ui->baudRate->setCurrentText(QString("%1").arg(m_settings.m_baudRate)); ui->track->setChecked(m_settings.m_track); + ui->targets->setCurrentIndex(ui->targets->findText(m_settings.m_target)); + ui->azimuthOffset->setValue(m_settings.m_azimuthOffset); + ui->elevationOffset->setValue(m_settings.m_elevationOffset); blockApplySettings(false); } @@ -198,102 +197,34 @@ void GS232ControllerGUI::updateSerialPortList() } } -void GS232ControllerGUI::updateDeviceSetList() +void GS232ControllerGUI::updatePipeList() { - MainWindow *mainWindow = MainWindow::getInstance(); - std::vector& deviceUISets = mainWindow->getDeviceUISets(); - std::vector::const_iterator it = deviceUISets.begin(); + QString currentText = ui->targets->currentText(); + ui->targets->blockSignals(true); + ui->targets->clear(); + QList::const_iterator it = m_availablePipes.begin(); - ui->device->blockSignals(true); - - ui->device->clear(); - unsigned int deviceIndex = 0; - - for (; it != deviceUISets.end(); ++it, deviceIndex++) + for (int i = 0; it != m_availablePipes.end(); ++it, i++) { - DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine; - - if (deviceSourceEngine) { - ui->device->addItem(QString("R%1").arg(deviceIndex), deviceIndex); - } + ui->targets->addItem(it->getName()); } - int newDeviceIndex; - - if (it != deviceUISets.begin()) + if (currentText.isEmpty()) { - if (m_settings.m_deviceIndex < 0) { - ui->device->setCurrentIndex(0); - } else { - ui->device->setCurrentIndex(m_settings.m_deviceIndex); - } - - newDeviceIndex = ui->device->currentData().toInt(); + if (m_availablePipes.size() > 0) + ui->targets->setCurrentIndex(0); } else + ui->targets->setCurrentIndex(ui->targets->findText(currentText)); + ui->targets->blockSignals(false); + + QString newText = ui->targets->currentText(); + if (currentText != newText) { - newDeviceIndex = -1; + m_settings.m_target = newText; + ui->targetName->setText(""); + applySettings(); } - - - if (newDeviceIndex != m_settings.m_deviceIndex) - { - qDebug("GS232ControllerGUI::updateDeviceSetLists: device index changed: %d", newDeviceIndex); - m_settings.m_deviceIndex = newDeviceIndex; - } - - updateChannelList(); - - ui->device->blockSignals(false); -} - -bool GS232ControllerGUI::updateChannelList() -{ - int newChannelIndex; - ui->channel->blockSignals(true); - ui->channel->clear(); - - if (m_settings.m_deviceIndex < 0) - { - newChannelIndex = -1; - } - else - { - MainWindow *mainWindow = MainWindow::getInstance(); - std::vector& deviceUISets = mainWindow->getDeviceUISets(); - DeviceUISet *deviceUISet = deviceUISets[m_settings.m_deviceIndex]; - int nbChannels = deviceUISet->getNumberOfChannels(); - - for (int ch = 0; ch < nbChannels; ch++) { - ui->channel->addItem(QString("%1").arg(ch), ch); - } - - if (nbChannels > 0) - { - if (m_settings.m_channelIndex < 0) { - ui->channel->setCurrentIndex(0); - } else { - ui->channel->setCurrentIndex(m_settings.m_channelIndex); - } - - newChannelIndex = ui->channel->currentIndex(); - } - else - { - newChannelIndex = -1; - } - } - - ui->channel->blockSignals(false); - - if (newChannelIndex != m_settings.m_channelIndex) - { - qDebug("GS232ControllerGUI::updateChannelList: channel index changed: %d", newChannelIndex); - m_settings.m_channelIndex = newChannelIndex; - return true; - } - - return false; } void GS232ControllerGUI::leaveEvent(QEvent*) @@ -346,32 +277,6 @@ void GS232ControllerGUI::on_startStop_toggled(bool checked) } } -void GS232ControllerGUI::on_devicesRefresh_clicked() -{ - updateDeviceSetList(); - displaySettings(); - applySettings(); -} - -void GS232ControllerGUI::on_device_currentIndexChanged(int index) -{ - if (index >= 0) - { - m_settings.m_deviceIndex = ui->device->currentData().toInt(); - updateChannelList(); - applySettings(); - } -} - -void GS232ControllerGUI::on_channel_currentIndexChanged(int index) -{ - if (index >= 0) - { - m_settings.m_channelIndex = index; - applySettings(); - } -} - void GS232ControllerGUI::on_serialPort_currentIndexChanged(int index) { (void) index; @@ -389,23 +294,43 @@ void GS232ControllerGUI::on_baudRate_currentIndexChanged(int index) void GS232ControllerGUI::on_azimuth_valueChanged(int value) { m_settings.m_azimuth = value; + ui->targetName->setText(""); applySettings(); } void GS232ControllerGUI::on_elevation_valueChanged(int value) { m_settings.m_elevation = value; + ui->targetName->setText(""); + applySettings(); +} + +void GS232ControllerGUI::on_azimuthOffset_valueChanged(int value) +{ + m_settings.m_azimuthOffset = value; + applySettings(); +} + +void GS232ControllerGUI::on_elevationOffset_valueChanged(int value) +{ + m_settings.m_elevationOffset = value; applySettings(); } void GS232ControllerGUI::on_track_stateChanged(int state) { m_settings.m_track = state == Qt::Checked; - ui->devicesRefresh->setEnabled(m_settings.m_track); - ui->deviceLabel->setEnabled(m_settings.m_track); - ui->device->setEnabled(m_settings.m_track); - ui->channelLabel->setEnabled(m_settings.m_track); - ui->channel->setEnabled(m_settings.m_track); + ui->targetsLabel->setEnabled(m_settings.m_track); + ui->targets->setEnabled(m_settings.m_track); + if (!m_settings.m_track) + ui->targetName->setText(""); + applySettings(); +} + +void GS232ControllerGUI::on_targets_currentTextChanged(const QString& text) +{ + m_settings.m_target = text; + ui->targetName->setText(""); applySettings(); } @@ -415,15 +340,23 @@ void GS232ControllerGUI::updateStatus() if (m_lastFeatureState != state) { + // We set checked state of start/stop button, in case it was changed via API + bool oldState; switch (state) { case Feature::StNotStarted: ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); break; case Feature::StIdle: + oldState = ui->startStop->blockSignals(true); + ui->startStop->setChecked(false); + ui->startStop->blockSignals(oldState); ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); break; case Feature::StRunning: + oldState = ui->startStop->blockSignals(true); + ui->startStop->setChecked(true); + ui->startStop->blockSignals(oldState); ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); break; case Feature::StError: diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index a8a41f62c..b43356a3d 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -23,6 +23,7 @@ #include "feature/featuregui.h" #include "util/messagequeue.h" +#include "pipes/pipeendpoint.h" #include "gs232controllersettings.h" class PluginAPI; @@ -50,6 +51,7 @@ private: FeatureUISet* m_featureUISet; GS232ControllerSettings m_settings; bool m_doApplySettings; + QList m_availablePipes; GS232Controller* m_gs232Controller; MessageQueue m_inputMessageQueue; @@ -62,9 +64,8 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); void displaySettings(); + void updatePipeList(); void updateSerialPortList(); - void updateDeviceSetList(); - bool updateChannelList(); //!< true if channel index has changed bool handleMessage(const Message& message); void leaveEvent(QEvent*); @@ -75,14 +76,14 @@ private slots: void onWidgetRolled(QWidget* widget, bool rollDown); void handleInputMessages(); void on_startStop_toggled(bool checked); - void on_devicesRefresh_clicked(); - void on_device_currentIndexChanged(int index); - void on_channel_currentIndexChanged(int index); void on_serialPort_currentIndexChanged(int index); void on_baudRate_currentIndexChanged(int index); void on_track_stateChanged(int state); void on_azimuth_valueChanged(int value); void on_elevation_valueChanged(int value); + void on_targets_currentTextChanged(const QString& text); + void on_azimuthOffset_valueChanged(int value); + void on_elevationOffset_valueChanged(int value); void updateStatus(); }; diff --git a/plugins/feature/gs232controller/gs232controllergui.ui b/plugins/feature/gs232controller/gs232controllergui.ui index 5189f070b..71b594c3c 100644 --- a/plugins/feature/gs232controller/gs232controllergui.ui +++ b/plugins/feature/gs232controller/gs232controllergui.ui @@ -7,7 +7,7 @@ 0 0 320 - 187 + 175 @@ -24,7 +24,7 @@ - 320 + 350 16777215 @@ -43,7 +43,7 @@ 10 10 301 - 171 + 161 @@ -179,6 +179,74 @@ + + + + + + Check to enable automatic tracking of azimuth and elevation from the specified channel + + + Track + + + + + + + Source + + + + + + + + 150 + 0 + + + + Target to track + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Target + + + + + + + Name of the target being tracked as indicated by the source channel / feature + + + true + + + + + @@ -271,107 +339,50 @@ - + - - - Check to enable automatic tracking of azimuth and elevation from the specified channel - + - Track + Azimuth offset - - - - 24 - 16777215 - - + - Refresh indexes of available device sets + Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment - - + + -360 - - - :/recycle.png:/recycle.png + + 360 - + - Device + Elevation offset - - - - 55 - 0 - - + - Receiver deviceset index + Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment + + + -180 + + + 180 + + + 1 - - - - Channel - - - - - - - - 55 - 0 - - - - Channel index - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -390,6 +401,18 @@
gui/buttonswitch.h
+ + startStop + azimuth + elevation + track + targets + targetName + serialPort + baudRate + azimuthOffset + elevationOffset + diff --git a/plugins/feature/gs232controller/gs232controllerreport.h b/plugins/feature/gs232controller/gs232controllerreport.h index 8e175d8fc..52699961e 100644 --- a/plugins/feature/gs232controller/gs232controllerreport.h +++ b/plugins/feature/gs232controller/gs232controllerreport.h @@ -27,7 +27,6 @@ class GS232ControllerReport : public QObject { Q_OBJECT public: - enum AzAlType {TARGET, ACTUAL}; class MsgReportAzAl : public Message { MESSAGE_CLASS_DECLARATION @@ -35,23 +34,20 @@ public: public: float getAzimuth() const { return m_azimuth; } float getElevation() const { return m_elevation; } - AzAlType getType() const { return m_type; } - static MsgReportAzAl* create(float azimuth, float elevation, AzAlType type) + static MsgReportAzAl* create(float azimuth, float elevation) { - return new MsgReportAzAl(azimuth, elevation, type); + return new MsgReportAzAl(azimuth, elevation); } private: float m_azimuth; float m_elevation; - AzAlType m_type; - MsgReportAzAl(float azimuth, float elevation, AzAlType type) : + MsgReportAzAl(float azimuth, float elevation) : Message(), m_azimuth(azimuth), - m_elevation(elevation), - m_type(type) + m_elevation(elevation) { } }; diff --git a/plugins/feature/gs232controller/gs232controllersettings.cpp b/plugins/feature/gs232controller/gs232controllersettings.cpp index 66f02acdb..16cdec690 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.cpp +++ b/plugins/feature/gs232controller/gs232controllersettings.cpp @@ -23,7 +23,15 @@ #include "gs232controllersettings.h" -MESSAGE_CLASS_DEFINITION(GS232ControllerSettings::MsgChannelIndexChange, Message) +const QStringList GS232ControllerSettings::m_pipeTypes = { + QStringLiteral("ADSBDemod"), + QStringLiteral("StarTracker") +}; + +const QStringList GS232ControllerSettings::m_pipeURIs = { + QStringLiteral("sdrangel.channel.adsbdemod"), + QStringLiteral("sdrangel.feature.startracker") +}; GS232ControllerSettings::GS232ControllerSettings() { @@ -37,8 +45,7 @@ void GS232ControllerSettings::resetToDefaults() m_serialPort = ""; m_baudRate = 9600; m_track = false; - m_deviceIndex = -1; - m_channelIndex = -1; + m_target = ""; m_title = "GS-232 Rotator Controller"; m_rgbColor = QColor(225, 25, 99).rgb(); m_useReverseAPI = false; @@ -46,6 +53,8 @@ void GS232ControllerSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIFeatureSetIndex = 0; m_reverseAPIFeatureIndex = 0; + m_azimuthOffset = 0; + m_elevationOffset = 0; } QByteArray GS232ControllerSettings::serialize() const @@ -57,8 +66,7 @@ QByteArray GS232ControllerSettings::serialize() const s.writeString(3, m_serialPort); s.writeS32(4, m_baudRate); s.writeBool(5, m_track); - s.writeS32(6, m_deviceIndex); - s.writeS32(7, m_channelIndex); + s.writeString(6, m_target); s.writeString(8, m_title); s.writeU32(9, m_rgbColor); s.writeBool(10, m_useReverseAPI); @@ -66,6 +74,8 @@ QByteArray GS232ControllerSettings::serialize() const s.writeU32(12, m_reverseAPIPort); s.writeU32(13, m_reverseAPIFeatureSetIndex); s.writeU32(14, m_reverseAPIFeatureIndex); + s.writeS32(15, m_azimuthOffset); + s.writeS32(16, m_elevationOffset); return s.final(); } @@ -91,8 +101,7 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data) d.readString(3, &m_serialPort, ""); d.readS32(4, &m_baudRate, 9600); d.readBool(5, &m_track, false); - d.readS32(6, &m_deviceIndex, -1); - d.readS32(7, &m_channelIndex, -1); + d.readString(6, &m_target, ""); d.readString(8, &m_title, "GS-232 Rotator Controller"); d.readU32(9, &m_rgbColor, QColor(225, 25, 99).rgb()); d.readBool(10, &m_useReverseAPI, false); @@ -109,6 +118,8 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data) m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp; d.readU32(14, &utmp, 0); m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp; + d.readS32(15, &m_azimuthOffset, 0); + d.readS32(16, &m_elevationOffset, 0); return true; } diff --git a/plugins/feature/gs232controller/gs232controllersettings.h b/plugins/feature/gs232controller/gs232controllersettings.h index 01cd25992..6eef7b78f 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.h +++ b/plugins/feature/gs232controller/gs232controllersettings.h @@ -25,35 +25,18 @@ #include "util/message.h" class Serializable; +class PipeEndPoint; struct GS232ControllerSettings { - class MsgChannelIndexChange : public Message { - MESSAGE_CLASS_DECLARATION - - public: - bool getIndex() const { return m_index; } - - static MsgChannelIndexChange* create(int index) { - return new MsgChannelIndexChange(index); - } - - protected: - int m_index; - - MsgChannelIndexChange(int index) : - Message(), - m_index(index) - { } - }; - int m_azimuth; int m_elevation; QString m_serialPort; int m_baudRate; - int m_deviceIndex; bool m_track; - int m_channelIndex; + QString m_target; // Plugin to get az/el from. E.g: "R0:0 ADSBDemod". Use a string, so can be set via WebAPI + int m_azimuthOffset; + int m_elevationOffset; QString m_title; quint32 m_rgbColor; bool m_useReverseAPI; @@ -66,6 +49,9 @@ struct GS232ControllerSettings void resetToDefaults(); QByteArray serialize() const; bool deserialize(const QByteArray& data); + + static const QStringList m_pipeTypes; + static const QStringList m_pipeURIs; }; #endif // INCLUDE_FEATURE_GS232CONTROLLERSETTINGS_H_ diff --git a/plugins/feature/gs232controller/gs232controllerworker.cpp b/plugins/feature/gs232controller/gs232controllerworker.cpp index 59af9333b..25ba64ac0 100644 --- a/plugins/feature/gs232controller/gs232controllerworker.cpp +++ b/plugins/feature/gs232controller/gs232controllerworker.cpp @@ -24,25 +24,14 @@ #include #include -#include "SWGDeviceState.h" -#include "SWGSuccessResponse.h" -#include "SWGErrorResponse.h" -#include "SWGDeviceSettings.h" -#include "SWGChannelSettings.h" -#include "SWGDeviceSet.h" -#include "SWGChannelReport.h" - -#include "webapi/webapiadapterinterface.h" -#include "webapi/webapiutils.h" - +#include "gs232controller.h" #include "gs232controllerworker.h" #include "gs232controllerreport.h" MESSAGE_CLASS_DEFINITION(GS232ControllerWorker::MsgConfigureGS232ControllerWorker, Message) MESSAGE_CLASS_DEFINITION(GS232ControllerReport::MsgReportAzAl, Message) -GS232ControllerWorker::GS232ControllerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : - m_webAPIAdapterInterface(webAPIAdapterInterface), +GS232ControllerWorker::GS232ControllerWorker() : m_msgQueueToFeature(nullptr), m_msgQueueToGUI(nullptr), m_running(false), @@ -113,10 +102,10 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting qDebug() << "GS232ControllerWorker::applySettings:" << " m_azimuth: " << settings.m_azimuth << " m_elevation: " << settings.m_elevation + << " m_azimuthOffset: " << settings.m_azimuthOffset + << " m_elevationOffset: " << settings.m_elevationOffset << " m_serialPort: " << settings.m_serialPort << " m_baudRate: " << settings.m_baudRate - << " m_deviceIndex: " << settings.m_deviceIndex - << " m_channelIndex: " << settings.m_channelIndex << " force: " << force; if ((settings.m_serialPort != m_settings.m_serialPort) || force) @@ -126,34 +115,57 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting m_serialPort.setPortName(settings.m_serialPort); m_serialPort.setBaudRate(settings.m_baudRate); if (!m_serialPort.open(QIODevice::ReadWrite)) + { qCritical() << "GS232ControllerWorker::applySettings: Failed to open serial port " << settings.m_serialPort << ". Error: " << m_serialPort.error(); + if (m_msgQueueToFeature) + m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Failed to open serial port %1: %2").arg(settings.m_serialPort).arg(m_serialPort.error()))); + } } else if ((settings.m_baudRate != m_settings.m_baudRate) || force) { m_serialPort.setBaudRate(settings.m_baudRate); } - if ((settings.m_elevation != m_settings.m_elevation) || force) + if ((settings.m_elevation != m_settings.m_elevation) + || (settings.m_elevationOffset != m_settings.m_elevationOffset) + || force) { - setAzimuthElevation(settings.m_azimuth, settings.m_elevation); + setAzimuthElevation(settings.m_azimuth, settings.m_elevation, settings.m_azimuthOffset, settings.m_elevationOffset); } - else if ((settings.m_azimuth != m_settings.m_azimuth) || force) + else if ((settings.m_azimuth != m_settings.m_azimuth) + || (settings.m_azimuthOffset != m_settings.m_azimuthOffset) + || force) { - setAzimuth(settings.m_azimuth); + setAzimuth(settings.m_azimuth, settings.m_azimuthOffset); } m_settings = settings; } -void GS232ControllerWorker::setAzimuth(int azimuth) +void GS232ControllerWorker::setAzimuth(int azimuth, int azimuthOffset) { + azimuth += azimuthOffset; + if (azimuth < 0) + azimuth = 0; + else if (azimuth > 450) + azimuth = 450; QString cmd = QString("M%1\r\n").arg(azimuth, 3, 10, QLatin1Char('0')); QByteArray data = cmd.toLatin1(); m_serialPort.write(data); } -void GS232ControllerWorker::setAzimuthElevation(int azimuth, int elevation) +void GS232ControllerWorker::setAzimuthElevation(int azimuth, int elevation, int azimuthOffset, int elevationOffset) { + azimuth += azimuthOffset; + if (azimuth < 0) + azimuth = 0; + else if (azimuth > 450) + azimuth = 450; + elevation += elevationOffset; + if (elevation < 0) + elevation = 0; + else if (elevation > 180) + elevation = 180; QString cmd = QString("W%1 %2\r\n").arg(azimuth, 3, 10, QLatin1Char('0')).arg(elevation, 3, 10, QLatin1Char('0')); QByteArray data = cmd.toLatin1(); m_serialPort.write(data); @@ -170,7 +182,6 @@ void GS232ControllerWorker::readSerialData() if (len != -1) { QString response = QString::fromUtf8(buf, len); - QRegularExpression re("AZ=(\\d\\d\\d)EL=(\\d\\d\\d)"); QRegularExpressionMatch match = re.match(response); if (match.hasMatch()) @@ -179,15 +190,17 @@ void GS232ControllerWorker::readSerialData() QString el = match.captured(2); //qDebug() << "GS232ControllerWorker::readSerialData read az " << az << " el " << el; if (getMessageQueueToGUI()) - { - GS232ControllerReport::MsgReportAzAl *msg = GS232ControllerReport::MsgReportAzAl::create( - az.toFloat(), el.toFloat(), GS232ControllerReport::ACTUAL); - getMessageQueueToGUI()->push(msg); - } + getMessageQueueToGUI()->push( GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat())); + } + else if (response == "\r\n") + { + // Ignore } else { - qDebug() << "GS232ControllerWorker::readSerialData unknown response " << response; + qDebug() << "GS232ControllerWorker::readSerialData - unexpected response " << response; + if (m_msgQueueToFeature) + m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 serial reponse: %1").arg(response))); } } } @@ -201,48 +214,4 @@ void GS232ControllerWorker::update() QByteArray cmd("C2\r\n"); m_serialPort.write(cmd); } - - // Request target Az/EL from channel - if (m_settings.m_track) - { - SWGSDRangel::SWGChannelReport response; - SWGSDRangel::SWGErrorResponse errorResponse; - - int httpRC = m_webAPIAdapterInterface->devicesetChannelReportGet( - m_settings.m_deviceIndex, - m_settings.m_channelIndex, - response, - errorResponse - ); - - if (httpRC/100 != 2) - { - qWarning("GS232ControllerWorker::update: get channel report error %d: %s", - httpRC, qPrintable(*errorResponse.getMessage())); - } - else - { - QJsonObject *jsonObj = response.asJsonObject(); - double targetAzimuth; - double targetElevation; - bool gotElevation = false; - bool gotAzimuth = false; - - if (WebAPIUtils::getSubObjectDouble(*jsonObj, "targetAzimuth", targetAzimuth)) - gotAzimuth = true; - - if (WebAPIUtils::getSubObjectDouble(*jsonObj, "targetElevation", targetElevation)) - gotElevation = true; - - if (gotAzimuth && gotElevation) - { - if (getMessageQueueToGUI()) - { - GS232ControllerReport::MsgReportAzAl *msg = GS232ControllerReport::MsgReportAzAl::create( - targetAzimuth, targetElevation, GS232ControllerReport::TARGET); - getMessageQueueToGUI()->push(msg); - } - } - } - } } diff --git a/plugins/feature/gs232controller/gs232controllerworker.h b/plugins/feature/gs232controller/gs232controllerworker.h index 2041e17c8..3be417fe2 100644 --- a/plugins/feature/gs232controller/gs232controllerworker.h +++ b/plugins/feature/gs232controller/gs232controllerworker.h @@ -28,8 +28,6 @@ #include "gs232controllersettings.h" -class WebAPIAdapterInterface; - class GS232ControllerWorker : public QObject { Q_OBJECT @@ -57,7 +55,7 @@ public: { } }; - GS232ControllerWorker(WebAPIAdapterInterface *webAPIAdapterInterface); + GS232ControllerWorker(); ~GS232ControllerWorker(); void reset(); bool startWork(); @@ -69,7 +67,6 @@ public: private: - WebAPIAdapterInterface *m_webAPIAdapterInterface; MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication MessageQueue *m_msgQueueToFeature; //!< Queue to report channel change to main feature object MessageQueue *m_msgQueueToGUI; @@ -82,8 +79,8 @@ private: bool handleMessage(const Message& cmd); void applySettings(const GS232ControllerSettings& settings, bool force = false); MessageQueue *getMessageQueueToGUI() { return m_msgQueueToGUI; } - void setAzimuth(int azimuth); - void setAzimuthElevation(int azimuth, int elevation); + void setAzimuth(int azimuth, int azimuthOffset); + void setAzimuthElevation(int azimuth, int elevation, int azimuthOffset, int elevationOffset); private slots: void handleInputMessages(); diff --git a/plugins/feature/gs232controller/readme.md b/plugins/feature/gs232controller/readme.md index 3e55f92ea..51bff3925 100644 --- a/plugins/feature/gs232controller/readme.md +++ b/plugins/feature/gs232controller/readme.md @@ -4,11 +4,11 @@ The GS-232 Rotator Controller feature plugin allows SDRangel to send commands to GS-232 rotators. This allows SDRangel to point antennas mounted on a rotator to a specified azimuth and elevation. -Azimuth and elevation can be set manually by a user in the GUI, via the REST API, or via another plugin, such as the ADS-B Demodulator, which can track a selected aircraft. +Azimuth and elevation can be set manually by a user in the GUI, via the REST API, or via another plugin, such as the ADS-B Demodulator, which can track a selected aircraft, or the Star Tracker, for radio astronomy or EME communication.

Interface

-![File source channel plugin GUI](../../../doc/img/GS232Controller_plugin.png) +![GS232 Rotator Controller feature plugin GUI](../../../doc/img/GS232Controller_plugin.png)

1: Start/Stop plugin

@@ -16,37 +16,50 @@ This button starts or stops the plugin. When the plugin is stopped, azimuth and

2: Azimuth

-Specifies the target azimuth (angle in degrees, clockwise from North) to point the antenna towards. Valid values range from 0 to 450 degrees. The value to the right of the target azimuth, is the current azimuth read from the GS-232 rotator. +Specifies the target azimuth (angle in degrees, clockwise from North) to point the antenna towards. Valid values range from 0 to 450 degrees. +The value to the right of the target azimuth, is the current azimuth read from the GS-232 rotator.

3: Elevation

-Specifies the target elevation (angle in degrees) to point the antenna towards. Valid values range from 0 to 180 degrees, where 0 and 180 point towards the horizon and 90 degrees to zenith. The value to the right of the target elevation, is the current elevation read from the GS-232 rotator. +Specifies the target elevation (angle in degrees) to point the antenna towards. Valid values range from 0 to 180 degrees, where 0 and 180 point towards the horizon and 90 degrees to zenith. +The value to the right of the target elevation, is the current elevation read from the GS-232 rotator. -

4: Serial Port

+

4: Track

+ +When checked, the target azimuth and elevation will be controlled by the Channel or Feature Source (5). +For example, this allows an aircraft to be tracked, by setting the Source to the ADS-B Demodulator plugin, or the Moon to be tracked by settng Source to the Star Tracker plugin. + +

5: Source

+ +Specify the SDRangel Channel or Feature that that will control the target aziumth and elevation values, when Track (4) is checked. + +

6: Target

+ +When tracking is enabled, this field will display a name for the target being tracked, as indicated by the selected Source plugin (5). +For example, the ADS-B plugin will display the flight number of the target aircraft. The Star Tracker plugin will display Sun, Moon or Star. + +

7: Serial Port

Specifies the serial port (E.g. COM3 on Windows or /dev/ttyS0 on Linux) that will be used to send commands to the GS-232 rotator. -

5: Baud rate

+

8: Baud rate

Specifies the baud rate that will be used to send commands to the GS-232 rotator. Typically this is 9600. -

6: Track

+

9: Azimuth Offset

-When checked, the GS-232 Rotator Controller plugin will query the channel specified by the Device (8) and Channel (9) combo boxes for the target azimuth and elevation. For example, this allows an aircraft to be tracked, by setting the Device and Channel to correspond to the ADS-B Demodulator plugin. +The azimuth offset specifies an angle in degrees that is added to the target azimuth before sending to the controller. This allows for a misalignment of the rotator to be corrected. -

7: Refresh list of devices and channels

+

10: Elevation Offset

-Use this button to refresh the list of devices (8) and channels (9) +The elevation offset specifies an angle in degrees that is added to the target elevation before sending to the controller. This allows for a misalignment of the rotator to be corrected. -

8: Select device set

+

API

-Specify the SDRangel device set containing the channel plugin that will be asked for aziumth and elevation values. Defaults to R0. +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: -

9: Select channel

+ curl -X PATCH "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/settings" -d '{"featureType": "GS232Controller", "GS232ControllerSettings": { "azimuth": 180, "elevation": 45 }}' -The channel index specifies the SDRangel channel that will be asked for azimuth and elevation values. Defaults to 0. +To start sending commands to the rotator: -

Developer Information

- -For a channel plugin to be able to set the azimuth and elevation, its channel report should contain targetAzimuth and targetElevation. See the ADS-B plugin as an example. - \ No newline at end of file + curl -X POST "http://127.0.0.1:8091/sdrangel/featureset/0/feature/0/run"