mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-15 04:41:55 -05:00
GS232 Rotator Controller updates
Add support for hamlib/rotctld protocol. Add support for TCP connections. Name plugin Rotator Controller, rather than GS-232 Rotator Controller, as it now supports 3 different protocols.
This commit is contained in:
parent
a41d0319dc
commit
257b265ee8
@ -127,6 +127,8 @@ void GS232ControllerGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|||||||
{
|
{
|
||||||
(void) widget;
|
(void) widget;
|
||||||
(void) rollDown;
|
(void) rollDown;
|
||||||
|
m_settings.m_rollupState = saveState();
|
||||||
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
|
GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
|
||||||
@ -179,10 +181,14 @@ void GS232ControllerGUI::displaySettings()
|
|||||||
ui->azimuth->setValue(m_settings.m_azimuth);
|
ui->azimuth->setValue(m_settings.m_azimuth);
|
||||||
ui->elevation->setValue(m_settings.m_elevation);
|
ui->elevation->setValue(m_settings.m_elevation);
|
||||||
ui->protocol->setCurrentIndex((int)m_settings.m_protocol);
|
ui->protocol->setCurrentIndex((int)m_settings.m_protocol);
|
||||||
|
ui->connection->setCurrentIndex((int)m_settings.m_connection);
|
||||||
updateDecimals(m_settings.m_protocol);
|
updateDecimals(m_settings.m_protocol);
|
||||||
if (m_settings.m_serialPort.length() > 0)
|
if (m_settings.m_serialPort.length() > 0) {
|
||||||
ui->serialPort->lineEdit()->setText(m_settings.m_serialPort);
|
ui->serialPort->lineEdit()->setText(m_settings.m_serialPort);
|
||||||
|
}
|
||||||
ui->baudRate->setCurrentText(QString("%1").arg(m_settings.m_baudRate));
|
ui->baudRate->setCurrentText(QString("%1").arg(m_settings.m_baudRate));
|
||||||
|
ui->host->setText(m_settings.m_host);
|
||||||
|
ui->port->setValue(m_settings.m_port);
|
||||||
ui->track->setChecked(m_settings.m_track);
|
ui->track->setChecked(m_settings.m_track);
|
||||||
ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source));
|
ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source));
|
||||||
ui->azimuthOffset->setValue(m_settings.m_azimuthOffset);
|
ui->azimuthOffset->setValue(m_settings.m_azimuthOffset);
|
||||||
@ -192,9 +198,24 @@ void GS232ControllerGUI::displaySettings()
|
|||||||
ui->elevationMin->setValue(m_settings.m_elevationMin);
|
ui->elevationMin->setValue(m_settings.m_elevationMin);
|
||||||
ui->elevationMax->setValue(m_settings.m_elevationMax);
|
ui->elevationMax->setValue(m_settings.m_elevationMax);
|
||||||
ui->tolerance->setValue(m_settings.m_tolerance);
|
ui->tolerance->setValue(m_settings.m_tolerance);
|
||||||
|
restoreState(m_settings.m_rollupState);
|
||||||
|
updateConnectionWidgets();
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GS232ControllerGUI::updateConnectionWidgets()
|
||||||
|
{
|
||||||
|
bool serial = m_settings.m_connection == GS232ControllerSettings::SERIAL;
|
||||||
|
ui->serialPortLabel->setVisible(serial);
|
||||||
|
ui->serialPort->setVisible(serial);
|
||||||
|
ui->baudRateLabel->setVisible(serial);
|
||||||
|
ui->baudRate->setVisible(serial);
|
||||||
|
ui->hostLabel->setVisible(!serial);
|
||||||
|
ui->host->setVisible(!serial);
|
||||||
|
ui->portLabel->setVisible(!serial);
|
||||||
|
ui->port->setVisible(!serial);
|
||||||
|
}
|
||||||
|
|
||||||
void GS232ControllerGUI::updateSerialPortList()
|
void GS232ControllerGUI::updateSerialPortList()
|
||||||
{
|
{
|
||||||
ui->serialPort->clear();
|
ui->serialPort->clear();
|
||||||
@ -315,6 +336,13 @@ void GS232ControllerGUI::on_protocol_currentIndexChanged(int index)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GS232ControllerGUI::on_connection_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_connection = (GS232ControllerSettings::Connection)index;
|
||||||
|
applySettings();
|
||||||
|
updateConnectionWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
void GS232ControllerGUI::on_serialPort_currentIndexChanged(int index)
|
void GS232ControllerGUI::on_serialPort_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
(void) index;
|
(void) index;
|
||||||
@ -329,6 +357,18 @@ void GS232ControllerGUI::on_baudRate_currentIndexChanged(int index)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GS232ControllerGUI::on_host_editingFinished()
|
||||||
|
{
|
||||||
|
m_settings.m_host = ui->host->text();
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GS232ControllerGUI::on_port_valueChanged(int value)
|
||||||
|
{
|
||||||
|
m_settings.m_port = value;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void GS232ControllerGUI::on_azimuth_valueChanged(double value)
|
void GS232ControllerGUI::on_azimuth_valueChanged(double value)
|
||||||
{
|
{
|
||||||
m_settings.m_azimuth = (float)value;
|
m_settings.m_azimuth = (float)value;
|
||||||
@ -388,7 +428,7 @@ void GS232ControllerGUI::on_tolerance_valueChanged(double value)
|
|||||||
void GS232ControllerGUI::on_track_stateChanged(int state)
|
void GS232ControllerGUI::on_track_stateChanged(int state)
|
||||||
{
|
{
|
||||||
m_settings.m_track = state == Qt::Checked;
|
m_settings.m_track = state == Qt::Checked;
|
||||||
ui->targetsLabel->setEnabled(m_settings.m_track);
|
ui->targetName->setEnabled(m_settings.m_track);
|
||||||
ui->sources->setEnabled(m_settings.m_track);
|
ui->sources->setEnabled(m_settings.m_track);
|
||||||
|
|
||||||
if (!m_settings.m_track) {
|
if (!m_settings.m_track) {
|
||||||
@ -439,7 +479,7 @@ void GS232ControllerGUI::updateStatus()
|
|||||||
break;
|
break;
|
||||||
case Feature::StError:
|
case Feature::StError:
|
||||||
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
|
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
|
||||||
QMessageBox::information(this, tr("Message"), m_gs232Controller->getErrorMessage());
|
QMessageBox::critical(this, m_settings.m_title, m_gs232Controller->getErrorMessage());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -65,6 +65,7 @@ private:
|
|||||||
void blockApplySettings(bool block);
|
void blockApplySettings(bool block);
|
||||||
void applySettings(bool force = false);
|
void applySettings(bool force = false);
|
||||||
void displaySettings();
|
void displaySettings();
|
||||||
|
void updateConnectionWidgets();
|
||||||
void updateDecimals(GS232ControllerSettings::Protocol protocol);
|
void updateDecimals(GS232ControllerSettings::Protocol protocol);
|
||||||
void updatePipeList();
|
void updatePipeList();
|
||||||
void updateSerialPortList();
|
void updateSerialPortList();
|
||||||
@ -79,7 +80,10 @@ private slots:
|
|||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
void on_startStop_toggled(bool checked);
|
void on_startStop_toggled(bool checked);
|
||||||
void on_protocol_currentIndexChanged(int index);
|
void on_protocol_currentIndexChanged(int index);
|
||||||
|
void on_connection_currentIndexChanged(int index);
|
||||||
void on_serialPort_currentIndexChanged(int index);
|
void on_serialPort_currentIndexChanged(int index);
|
||||||
|
void on_host_editingFinished();
|
||||||
|
void on_port_valueChanged(int value);
|
||||||
void on_baudRate_currentIndexChanged(int index);
|
void on_baudRate_currentIndexChanged(int index);
|
||||||
void on_track_stateChanged(int state);
|
void on_track_stateChanged(int state);
|
||||||
void on_azimuth_valueChanged(double value);
|
void on_azimuth_valueChanged(double value);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>360</width>
|
<width>360</width>
|
||||||
<height>231</height>
|
<height>281</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -37,17 +37,17 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>GS-232 Rotator Controller</string>
|
<string>GS-232 Rotator Controller</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="settingsContainer" native="true">
|
<widget class="QWidget" name="controlsContainer" native="true">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>341</width>
|
<width>341</width>
|
||||||
<height>211</height>
|
<height>81</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Settings</string>
|
<string>Controls</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
@ -184,34 +184,192 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="2" column="2">
|
<item row="0" column="1" colspan="2">
|
||||||
<widget class="QLabel" name="toleranceLabel">
|
<widget class="QComboBox" name="sources">
|
||||||
<property name="text">
|
<property name="minimumSize">
|
||||||
<string>Tolerance</string>
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Target to track</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="track">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Check to enable automatic tracking of azimuth and elevation from the specified channel</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Track</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLineEdit" name="targetName">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Name of the target being tracked as indicated by the source channel / feature</string>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="settingsContainer" native="true">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>110</y>
|
||||||
|
<width>341</width>
|
||||||
|
<height>161</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="settingsGridLayout">
|
||||||
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="azimuthOffsetLabel">
|
<widget class="QLabel" name="azimuthOffsetLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Azimuth offset</string>
|
<string>Azimuth offset</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="azimuthMinLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Azimuth min</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QSpinBox" name="azimuthOffset">
|
<widget class="QSpinBox" name="azimuthMin">
|
||||||
<property name="toolTip">
|
|
||||||
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-360</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>360</number>
|
<number>450</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="protocolLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Protocol</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2">
|
||||||
|
<widget class="QLabel" name="elevationMaxLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Elevation max</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="3">
|
<item row="4" column="3">
|
||||||
|
<widget class="QSpinBox" name="azimuthMax">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>450</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="connectionLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Connection</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="elevationMin">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>180</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLabel" name="portLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Port</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="tolerance">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Tolerance in degrees</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="serialPortLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial Port</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QComboBox" name="connection">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The type of connection to use to the rotator</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>TCP</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="toleranceLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tolerance</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QLabel" name="elevationOffsetLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Elevation offset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="elevationMinLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Elevation min</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
<widget class="QSpinBox" name="elevationOffset">
|
<widget class="QSpinBox" name="elevationOffset">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
||||||
@ -227,7 +385,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="host">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Host name / IP address of computer running rotctld</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="serialPort">
|
<widget class="QComboBox" name="serialPort">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Name of serial port to use to connect to the GS-232 controller</string>
|
<string>Name of serial port to use to connect to the GS-232 controller</string>
|
||||||
@ -237,7 +402,43 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="3">
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="protocol">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Command protocol</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>GS-232</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SPID</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>rotctld</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="hostLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Host</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="3">
|
||||||
|
<widget class="QSpinBox" name="elevationMax">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>180</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
<widget class="QComboBox" name="baudRate">
|
<widget class="QComboBox" name="baudRate">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Serial port baud rate for the GS-232 controller</string>
|
<string>Serial port baud rate for the GS-232 controller</string>
|
||||||
@ -297,161 +498,40 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="serialLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Serial Port</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QLabel" name="elevationOffsetLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Elevation offset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="2">
|
|
||||||
<widget class="QLabel" name="elevationMaxLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Elevation max</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QSpinBox" name="elevationMin">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>180</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="protocol">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Command protocol</string>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>GS-232</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>SPID</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="azimuthMinLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Azimuth min</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="3">
|
|
||||||
<widget class="QSpinBox" name="azimuthMax">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>450</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="protocolLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Protocol</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="3">
|
|
||||||
<widget class="QSpinBox" name="elevationMax">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>180</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="elevationMinLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Elevation min</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QLabel" name="baudRateLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Baud rate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QSpinBox" name="azimuthMin">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>450</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="2">
|
|
||||||
<widget class="QLabel" name="azimuthMaxLabel">
|
<widget class="QLabel" name="azimuthMaxLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Azimuth max</string>
|
<string>Azimuth max</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="3" column="1">
|
||||||
<widget class="QCheckBox" name="track">
|
<widget class="QSpinBox" name="azimuthOffset">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Check to enable automatic tracking of azimuth and elevation from the specified channel</string>
|
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="minimum">
|
||||||
<string>Track</string>
|
<number>-360</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="maximum">
|
||||||
</item>
|
<number>360</number>
|
||||||
<item row="1" column="2" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="targetName">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Name of the target being tracked as indicated by the source channel / feature</string>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="targetNameLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Target</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="targetsLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Source</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2" colspan="2">
|
|
||||||
<widget class="QComboBox" name="sources">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>150</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Target to track</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="3">
|
<item row="2" column="3">
|
||||||
<widget class="QDoubleSpinBox" name="tolerance">
|
<widget class="QSpinBox" name="port">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Tolerance in degrees</string>
|
<string>TCP port number rotctld is listening on</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="decimals">
|
<property name="maximum">
|
||||||
<number>1</number>
|
<number>65535</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QLabel" name="baudRateLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Baud rate</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -479,17 +559,6 @@
|
|||||||
<tabstop>elevation</tabstop>
|
<tabstop>elevation</tabstop>
|
||||||
<tabstop>track</tabstop>
|
<tabstop>track</tabstop>
|
||||||
<tabstop>sources</tabstop>
|
<tabstop>sources</tabstop>
|
||||||
<tabstop>targetName</tabstop>
|
|
||||||
<tabstop>protocol</tabstop>
|
|
||||||
<tabstop>tolerance</tabstop>
|
|
||||||
<tabstop>serialPort</tabstop>
|
|
||||||
<tabstop>baudRate</tabstop>
|
|
||||||
<tabstop>azimuthOffset</tabstop>
|
|
||||||
<tabstop>elevationOffset</tabstop>
|
|
||||||
<tabstop>azimuthMin</tabstop>
|
|
||||||
<tabstop>azimuthMax</tabstop>
|
|
||||||
<tabstop>elevationMin</tabstop>
|
|
||||||
<tabstop>elevationMax</tabstop>
|
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
const PluginDescriptor GS232ControllerPlugin::m_pluginDescriptor = {
|
const PluginDescriptor GS232ControllerPlugin::m_pluginDescriptor = {
|
||||||
GS232Controller::m_featureId,
|
GS232Controller::m_featureId,
|
||||||
QStringLiteral("GS-232 Rotator Controller"),
|
QStringLiteral("Rotator Controller"),
|
||||||
QStringLiteral("6.17.2"),
|
QStringLiteral("6.17.4"),
|
||||||
QStringLiteral("(c) Jon Beniston, M7RCE"),
|
QStringLiteral("(c) Jon Beniston, M7RCE"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -50,7 +50,7 @@ void GS232ControllerSettings::resetToDefaults()
|
|||||||
m_baudRate = 9600;
|
m_baudRate = 9600;
|
||||||
m_track = false;
|
m_track = false;
|
||||||
m_source = "";
|
m_source = "";
|
||||||
m_title = "GS-232 Rotator Controller";
|
m_title = "Rotator Controller";
|
||||||
m_rgbColor = QColor(225, 25, 99).rgb();
|
m_rgbColor = QColor(225, 25, 99).rgb();
|
||||||
m_useReverseAPI = false;
|
m_useReverseAPI = false;
|
||||||
m_reverseAPIAddress = "127.0.0.1";
|
m_reverseAPIAddress = "127.0.0.1";
|
||||||
@ -63,8 +63,11 @@ void GS232ControllerSettings::resetToDefaults()
|
|||||||
m_azimuthMax = 450;
|
m_azimuthMax = 450;
|
||||||
m_elevationMin = 0;
|
m_elevationMin = 0;
|
||||||
m_elevationMax = 180;
|
m_elevationMax = 180;
|
||||||
m_tolerance = 0.0f;
|
m_tolerance = 1.0f;
|
||||||
m_protocol = GS232;
|
m_protocol = GS232;
|
||||||
|
m_connection = SERIAL;
|
||||||
|
m_host = "127.0.0.1";
|
||||||
|
m_port = 4533;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray GS232ControllerSettings::serialize() const
|
QByteArray GS232ControllerSettings::serialize() const
|
||||||
@ -92,6 +95,10 @@ QByteArray GS232ControllerSettings::serialize() const
|
|||||||
s.writeS32(20, m_elevationMax);
|
s.writeS32(20, m_elevationMax);
|
||||||
s.writeFloat(21, m_tolerance);
|
s.writeFloat(21, m_tolerance);
|
||||||
s.writeS32(22, (int)m_protocol);
|
s.writeS32(22, (int)m_protocol);
|
||||||
|
s.writeS32(23, (int)m_connection);
|
||||||
|
s.writeString(24, m_host);
|
||||||
|
s.writeS32(25, m_port);
|
||||||
|
s.writeBlob(26, m_rollupState);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
@ -118,7 +125,7 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
|
|||||||
d.readS32(4, &m_baudRate, 9600);
|
d.readS32(4, &m_baudRate, 9600);
|
||||||
d.readBool(5, &m_track, false);
|
d.readBool(5, &m_track, false);
|
||||||
d.readString(6, &m_source, "");
|
d.readString(6, &m_source, "");
|
||||||
d.readString(8, &m_title, "GS-232 Rotator Controller");
|
d.readString(8, &m_title, "Rotator Controller");
|
||||||
d.readU32(9, &m_rgbColor, QColor(225, 25, 99).rgb());
|
d.readU32(9, &m_rgbColor, QColor(225, 25, 99).rgb());
|
||||||
d.readBool(10, &m_useReverseAPI, false);
|
d.readBool(10, &m_useReverseAPI, false);
|
||||||
d.readString(11, &m_reverseAPIAddress, "127.0.0.1");
|
d.readString(11, &m_reverseAPIAddress, "127.0.0.1");
|
||||||
@ -140,8 +147,12 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
|
|||||||
d.readS32(18, &m_azimuthMax, 450);
|
d.readS32(18, &m_azimuthMax, 450);
|
||||||
d.readS32(19, &m_elevationMin, 0);
|
d.readS32(19, &m_elevationMin, 0);
|
||||||
d.readS32(20, &m_elevationMax, 180);
|
d.readS32(20, &m_elevationMax, 180);
|
||||||
d.readFloat(21, &m_tolerance, 0.0f);
|
d.readFloat(21, &m_tolerance, 1.0f);
|
||||||
d.readS32(22, (int*)&m_protocol, GS232);
|
d.readS32(22, (int*)&m_protocol, GS232);
|
||||||
|
d.readS32(23, (int*)&m_connection, SERIAL);
|
||||||
|
d.readString(24, &m_host, "127.0.0.1");
|
||||||
|
d.readS32(25, &m_port, 4533);
|
||||||
|
d.readBlob(26, &m_rollupState);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ struct GS232ControllerSettings
|
|||||||
float m_elevation;
|
float m_elevation;
|
||||||
QString m_serialPort;
|
QString m_serialPort;
|
||||||
int m_baudRate;
|
int m_baudRate;
|
||||||
|
QString m_host;
|
||||||
|
int m_port;
|
||||||
bool m_track;
|
bool m_track;
|
||||||
QString m_source; // Plugin to get az/el from. E.g: "R0:0 ADSBDemod". Use a string, so can be set via WebAPI
|
QString m_source; // 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_azimuthOffset;
|
||||||
@ -41,7 +43,9 @@ struct GS232ControllerSettings
|
|||||||
int m_elevationMin;
|
int m_elevationMin;
|
||||||
int m_elevationMax;
|
int m_elevationMax;
|
||||||
float m_tolerance;
|
float m_tolerance;
|
||||||
enum Protocol { GS232, SPID } m_protocol;
|
enum Protocol { GS232, SPID, ROTCTLD } m_protocol;
|
||||||
|
enum Connection { SERIAL, TCP } m_connection;
|
||||||
|
QByteArray m_rollupState;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
bool m_useReverseAPI;
|
bool m_useReverseAPI;
|
||||||
|
@ -35,11 +35,13 @@ GS232ControllerWorker::GS232ControllerWorker() :
|
|||||||
m_msgQueueToFeature(nullptr),
|
m_msgQueueToFeature(nullptr),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_mutex(QMutex::Recursive),
|
m_mutex(QMutex::Recursive),
|
||||||
|
m_device(nullptr),
|
||||||
m_lastAzimuth(-1.0f),
|
m_lastAzimuth(-1.0f),
|
||||||
m_lastElevation(-1.0f),
|
m_lastElevation(-1.0f),
|
||||||
m_spidSetOutstanding(false),
|
m_spidSetOutstanding(false),
|
||||||
m_spidSetSent(false),
|
m_spidSetSent(false),
|
||||||
m_spidStatusSent(false)
|
m_spidStatusSent(false),
|
||||||
|
m_rotCtlDReadAz(false)
|
||||||
{
|
{
|
||||||
connect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(update()));
|
connect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(update()));
|
||||||
m_pollTimer.start(1000);
|
m_pollTimer.start(1000);
|
||||||
@ -65,9 +67,12 @@ bool GS232ControllerWorker::startWork()
|
|||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
connect(&m_serialPort, &QSerialPort::readyRead, this, &GS232ControllerWorker::readSerialData);
|
connect(&m_serialPort, &QSerialPort::readyRead, this, &GS232ControllerWorker::readData);
|
||||||
if (!m_settings.m_serialPort.isEmpty()) {
|
connect(&m_socket, &QTcpSocket::readyRead, this, &GS232ControllerWorker::readData);
|
||||||
openSerialPort(m_settings);
|
if (m_settings.m_connection == GS232ControllerSettings::TCP) {
|
||||||
|
m_device = openSocket(m_settings);
|
||||||
|
} else {
|
||||||
|
m_device = openSerialPort(m_settings);
|
||||||
}
|
}
|
||||||
m_running = true;
|
m_running = true;
|
||||||
return m_running;
|
return m_running;
|
||||||
@ -77,10 +82,12 @@ void GS232ControllerWorker::stopWork()
|
|||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
// Close serial port as USB/controller activity can create RFI
|
// Close serial port as USB/controller activity can create RFI
|
||||||
if (m_serialPort.isOpen())
|
if (m_device && m_device->isOpen()) {
|
||||||
m_serialPort.close();
|
m_device->close();
|
||||||
|
}
|
||||||
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
disconnect(&m_serialPort, &QSerialPort::readyRead, this, &GS232ControllerWorker::readSerialData);
|
disconnect(&m_serialPort, &QSerialPort::readyRead, this, &GS232ControllerWorker::readData);
|
||||||
|
disconnect(&m_socket, &QTcpSocket::readyRead, this, &GS232ControllerWorker::readData);
|
||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,18 +132,34 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
|
|||||||
<< " m_elevationMax: " << settings.m_elevationMax
|
<< " m_elevationMax: " << settings.m_elevationMax
|
||||||
<< " m_tolerance: " << settings.m_tolerance
|
<< " m_tolerance: " << settings.m_tolerance
|
||||||
<< " m_protocol: " << settings.m_protocol
|
<< " m_protocol: " << settings.m_protocol
|
||||||
|
<< " m_connection: " << settings.m_connection
|
||||||
<< " m_serialPort: " << settings.m_serialPort
|
<< " m_serialPort: " << settings.m_serialPort
|
||||||
<< " m_baudRate: " << settings.m_baudRate
|
<< " m_baudRate: " << settings.m_baudRate
|
||||||
|
<< " m_host: " << settings.m_host
|
||||||
|
<< " m_port: " << settings.m_port
|
||||||
<< " force: " << force;
|
<< " force: " << force;
|
||||||
|
|
||||||
if ((settings.m_serialPort != m_settings.m_serialPort) || force)
|
if (settings.m_connection != m_settings.m_connection)
|
||||||
{
|
{
|
||||||
openSerialPort(settings);
|
if (m_device && m_device->isOpen()) {
|
||||||
|
m_device->close();
|
||||||
}
|
}
|
||||||
else if ((settings.m_baudRate != m_settings.m_baudRate) || force)
|
}
|
||||||
|
|
||||||
|
if (settings.m_connection == GS232ControllerSettings::TCP)
|
||||||
{
|
{
|
||||||
|
if ((settings.m_host != m_settings.m_host) || (settings.m_port != m_settings.m_port) || force) {
|
||||||
|
m_device = openSocket(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((settings.m_serialPort != m_settings.m_serialPort) || force) {
|
||||||
|
m_device = openSerialPort(settings);
|
||||||
|
} else if ((settings.m_baudRate != m_settings.m_baudRate) || force) {
|
||||||
m_serialPort.setBaudRate(settings.m_baudRate);
|
m_serialPort.setBaudRate(settings.m_baudRate);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply offset then clamp
|
// Apply offset then clamp
|
||||||
|
|
||||||
@ -159,22 +182,54 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
|
|||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GS232ControllerWorker::openSerialPort(const GS232ControllerSettings& settings)
|
QIODevice *GS232ControllerWorker::openSerialPort(const GS232ControllerSettings& settings)
|
||||||
{
|
{
|
||||||
|
qDebug() << "GS232ControllerWorker::openSerialPort: " << settings.m_serialPort;
|
||||||
if (m_serialPort.isOpen()) {
|
if (m_serialPort.isOpen()) {
|
||||||
m_serialPort.close();
|
m_serialPort.close();
|
||||||
}
|
}
|
||||||
|
m_lastAzimuth = -1;
|
||||||
|
m_lastElevation = -1;
|
||||||
|
if (!settings.m_serialPort.isEmpty())
|
||||||
|
{
|
||||||
m_serialPort.setPortName(settings.m_serialPort);
|
m_serialPort.setPortName(settings.m_serialPort);
|
||||||
m_serialPort.setBaudRate(settings.m_baudRate);
|
m_serialPort.setBaudRate(settings.m_baudRate);
|
||||||
if (!m_serialPort.open(QIODevice::ReadWrite))
|
if (!m_serialPort.open(QIODevice::ReadWrite))
|
||||||
{
|
{
|
||||||
qCritical() << "GS232ControllerWorker::openSerialPort: Failed to open serial port " << settings.m_serialPort << ". Error: " << m_serialPort.error();
|
qCritical() << "GS232ControllerWorker::openSerialPort: 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())));
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Failed to open serial port %1: %2").arg(settings.m_serialPort).arg(m_serialPort.error())));
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return &m_serialPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QIODevice *GS232ControllerWorker::openSocket(const GS232ControllerSettings& settings)
|
||||||
|
{
|
||||||
|
qDebug() << "GS232ControllerWorker::openSocket: " << settings.m_host << settings.m_port;
|
||||||
|
if (m_socket.isOpen()) {
|
||||||
|
m_socket.close();
|
||||||
}
|
}
|
||||||
m_lastAzimuth = -1;
|
m_lastAzimuth = -1;
|
||||||
m_lastElevation = -1;
|
m_lastElevation = -1;
|
||||||
|
m_socket.connectToHost(settings.m_host, settings.m_port);
|
||||||
|
if (m_socket.waitForConnected(3000))
|
||||||
|
{
|
||||||
|
return &m_socket;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qCritical() << "GS232ControllerWorker::openSocket: Failed to connect to " << settings.m_host << settings.m_port;
|
||||||
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Failed to connect to %1:%2").arg(settings.m_host).arg(settings.m_port)));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GS232ControllerWorker::setAzimuth(float azimuth)
|
void GS232ControllerWorker::setAzimuth(float azimuth)
|
||||||
@ -200,10 +255,8 @@ void GS232ControllerWorker::setAzimuthElevation(float azimuth, float elevation)
|
|||||||
QByteArray data = cmd.toLatin1();
|
QByteArray data = cmd.toLatin1();
|
||||||
m_serialPort.write(data);
|
m_serialPort.write(data);
|
||||||
}
|
}
|
||||||
else
|
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||||
{
|
{
|
||||||
qDebug() << "GS232ControllerWorker::setAzimuthElevation " << " AZ " << azimuth << " EL " << elevation;
|
|
||||||
|
|
||||||
if (!m_spidSetSent && !m_spidStatusSent)
|
if (!m_spidSetSent && !m_spidStatusSent)
|
||||||
{
|
{
|
||||||
QByteArray cmd(13, (char)0);
|
QByteArray cmd(13, (char)0);
|
||||||
@ -233,21 +286,25 @@ void GS232ControllerWorker::setAzimuthElevation(float azimuth, float elevation)
|
|||||||
qDebug() << "GS232ControllerWorker::setAzimuthElevation: Not sent, waiting for status reply";
|
qDebug() << "GS232ControllerWorker::setAzimuthElevation: Not sent, waiting for status reply";
|
||||||
m_spidSetOutstanding = true;
|
m_spidSetOutstanding = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
QString cmd = QString("P %1 %2\n").arg(azimuth).arg(elevation);
|
||||||
|
QByteArray data = cmd.toLatin1();
|
||||||
|
m_socket.write(data);
|
||||||
}
|
}
|
||||||
m_lastAzimuth = azimuth;
|
m_lastAzimuth = azimuth;
|
||||||
m_lastElevation = elevation;
|
m_lastElevation = elevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GS232ControllerWorker::readSerialData()
|
void GS232ControllerWorker::readData()
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
qint64 len;
|
qint64 len;
|
||||||
|
|
||||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||||
{
|
{
|
||||||
while (m_serialPort.canReadLine())
|
while (m_device->canReadLine())
|
||||||
{
|
{
|
||||||
len = m_serialPort.readLine(buf, sizeof(buf));
|
len = m_device->readLine(buf, sizeof(buf));
|
||||||
if (len != -1)
|
if (len != -1)
|
||||||
{
|
{
|
||||||
QString response = QString::fromUtf8(buf, len);
|
QString response = QString::fromUtf8(buf, len);
|
||||||
@ -258,7 +315,7 @@ void GS232ControllerWorker::readSerialData()
|
|||||||
{
|
{
|
||||||
QString az = match.captured(1);
|
QString az = match.captured(1);
|
||||||
QString el = match.captured(2);
|
QString el = match.captured(2);
|
||||||
//qDebug() << "GS232ControllerWorker::readSerialData read Az " << az << " El " << el;
|
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
|
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
|
||||||
}
|
}
|
||||||
else if (response == "\r\n")
|
else if (response == "\r\n")
|
||||||
@ -267,27 +324,27 @@ void GS232ControllerWorker::readSerialData()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "GS232ControllerWorker::readSerialData - unexpected GS-232 response \"" << response << "\"";
|
qWarning() << "GS232ControllerWorker::readData - unexpected GS-232 response \"" << response << "\"";
|
||||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 response: %1").arg(response)));
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 response: %1").arg(response)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||||
{
|
{
|
||||||
while (m_serialPort.bytesAvailable() >= 12)
|
while (m_device->bytesAvailable() >= 12)
|
||||||
{
|
{
|
||||||
len = m_serialPort.read(buf, 12);
|
len = m_device->read(buf, 12);
|
||||||
if ((len == 12) && (buf[0] == 0x57))
|
if ((len == 12) && (buf[0] == 0x57))
|
||||||
{
|
{
|
||||||
double az;
|
double az;
|
||||||
double el;
|
double el;
|
||||||
az = buf[1] * 100.0 + buf[2] * 10.0 + buf[3] + buf[4] / 10.0 - 360.0;
|
az = buf[1] * 100.0 + buf[2] * 10.0 + buf[3] + buf[4] / 10.0 - 360.0;
|
||||||
el = buf[6] * 100.0 + buf[7] * 10.0 + buf[8] + buf[9] / 10.0 - 360.0;
|
el = buf[6] * 100.0 + buf[7] * 10.0 + buf[8] + buf[9] / 10.0 - 360.0;
|
||||||
//qDebug() << "GS232ControllerWorker::readSerialData read Az " << az << " El " << el;
|
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||||
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az, el));
|
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az, el));
|
||||||
if (m_spidStatusSent && m_spidSetSent) {
|
if (m_spidStatusSent && m_spidSetSent) {
|
||||||
qDebug() << "GS232ControllerWorker::readSerialData - m_spidStatusSent and m_spidSetSent set simultaneously";
|
qDebug() << "GS232ControllerWorker::readData - m_spidStatusSent and m_spidSetSent set simultaneously";
|
||||||
}
|
}
|
||||||
if (m_spidStatusSent) {
|
if (m_spidStatusSent) {
|
||||||
m_spidStatusSent = false;
|
m_spidStatusSent = false;
|
||||||
@ -304,26 +361,95 @@ void GS232ControllerWorker::readSerialData()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
QByteArray bytes(buf, (int)len);
|
QByteArray bytes(buf, (int)len);
|
||||||
qDebug() << "GS232ControllerWorker::readSerialData - unexpected SPID rot2prog response \"" << bytes.toHex() << "\"";
|
qWarning() << "GS232ControllerWorker::readData - unexpected SPID rot2prog response \"" << bytes.toHex() << "\"";
|
||||||
if (m_msgQueueToFeature) {
|
|
||||||
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected SPID rot2prog response: %1").arg(bytes.toHex().data())));
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected SPID rot2prog response: %1").arg(bytes.toHex().data())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (m_device->canReadLine())
|
||||||
|
{
|
||||||
|
len = m_device->readLine(buf, sizeof(buf));
|
||||||
|
if (len != -1)
|
||||||
|
{
|
||||||
|
QString response = QString::fromUtf8(buf, len).trimmed();
|
||||||
|
QRegularExpression rprt("RPRT (-?\\d+)");
|
||||||
|
QRegularExpressionMatch matchRprt = rprt.match(response);
|
||||||
|
QRegularExpression decimal("(-?\\d+.\\d+)");
|
||||||
|
QRegularExpressionMatch matchDecimal = decimal.match(response);
|
||||||
|
if (matchRprt.hasMatch())
|
||||||
|
{
|
||||||
|
// See rig_errcode_e in hamlib rig.h
|
||||||
|
const QStringList errors = {
|
||||||
|
"OK",
|
||||||
|
"Invalid parameter",
|
||||||
|
"Invalid configuration",
|
||||||
|
"No memory",
|
||||||
|
"Not implemented",
|
||||||
|
"Timeout",
|
||||||
|
"IO error",
|
||||||
|
"Internal error",
|
||||||
|
"Protocol error",
|
||||||
|
"Command rejected",
|
||||||
|
"Arg truncated",
|
||||||
|
"Not available",
|
||||||
|
"VFO not targetable",
|
||||||
|
"Bus error",
|
||||||
|
"Collision on bus",
|
||||||
|
"NULL rig handled or invalid pointer parameter",
|
||||||
|
"Invalid VFO",
|
||||||
|
"Argument out of domain of function"
|
||||||
|
};
|
||||||
|
int rprt = matchRprt.captured(1).toInt();
|
||||||
|
if (rprt != 0)
|
||||||
|
{
|
||||||
|
qWarning() << "GS232ControllerWorker::readData - rotctld error: " << errors[-rprt];
|
||||||
|
// Seem to get a lot of EPROTO errors from rotctld due to extra 00 char in response to GS232 C2 command
|
||||||
|
// E.g: ./rotctld.exe -m 603 -r com7 -vvvvv
|
||||||
|
// read_string(): RX 16 characters
|
||||||
|
// 0000 00 41 5a 3d 31 37 35 20 20 45 4c 3d 30 33 38 0d .AZ=175 EL=038.
|
||||||
|
// So don't pass these to GUI for now
|
||||||
|
if (rprt != -8) {
|
||||||
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("rotctld error: %1").arg(errors[-rprt])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_rotCtlDReadAz = false;
|
||||||
|
}
|
||||||
|
else if (matchDecimal.hasMatch() && !m_rotCtlDReadAz)
|
||||||
|
{
|
||||||
|
m_rotCtlDAz = response;
|
||||||
|
m_rotCtlDReadAz = true;
|
||||||
|
}
|
||||||
|
else if (matchDecimal.hasMatch() && m_rotCtlDReadAz)
|
||||||
|
{
|
||||||
|
QString az = m_rotCtlDAz;
|
||||||
|
QString el = response;
|
||||||
|
m_rotCtlDReadAz = false;
|
||||||
|
//qDebug() << "GS232ControllerWorker::readData read Az " << az << " El " << el;
|
||||||
|
m_msgQueueToFeature->push(GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "GS232ControllerWorker::readData - Unexpected rotctld response \"" << response << "\"";
|
||||||
|
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected rotctld response: %1").arg(response)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GS232ControllerWorker::update()
|
void GS232ControllerWorker::update()
|
||||||
{
|
{
|
||||||
// Request current Az/El from GS-232 controller
|
// Request current Az/El from controller
|
||||||
if (m_serialPort.isOpen())
|
if (m_device && m_device->isOpen())
|
||||||
{
|
{
|
||||||
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
|
||||||
{
|
{
|
||||||
QByteArray cmd("C2\r\n");
|
QByteArray cmd("C2\r\n");
|
||||||
m_serialPort.write(cmd);
|
m_device->write(cmd);
|
||||||
}
|
}
|
||||||
else
|
else if (m_settings.m_protocol == GS232ControllerSettings::SPID)
|
||||||
{
|
{
|
||||||
// Don't send a new status command, if waiting for a previous reply
|
// Don't send a new status command, if waiting for a previous reply
|
||||||
if (!m_spidSetSent && !m_spidStatusSent)
|
if (!m_spidSetSent && !m_spidStatusSent)
|
||||||
@ -336,9 +462,14 @@ void GS232ControllerWorker::update()
|
|||||||
}
|
}
|
||||||
cmd.append((char)0x1f); // Status
|
cmd.append((char)0x1f); // Status
|
||||||
cmd.append((char)0x20); // End
|
cmd.append((char)0x20); // End
|
||||||
m_serialPort.write(cmd);
|
m_device->write(cmd);
|
||||||
m_spidStatusSent = true;
|
m_spidStatusSent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QByteArray cmd("p\n");
|
||||||
|
m_device->write(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSerialPort>
|
#include <QSerialPort>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
@ -71,7 +72,9 @@ private:
|
|||||||
GS232ControllerSettings m_settings;
|
GS232ControllerSettings m_settings;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
|
QIODevice *m_device;
|
||||||
QSerialPort m_serialPort;
|
QSerialPort m_serialPort;
|
||||||
|
QTcpSocket m_socket;
|
||||||
QTimer m_pollTimer;
|
QTimer m_pollTimer;
|
||||||
|
|
||||||
float m_lastAzimuth;
|
float m_lastAzimuth;
|
||||||
@ -81,15 +84,19 @@ private:
|
|||||||
bool m_spidSetSent;
|
bool m_spidSetSent;
|
||||||
bool m_spidStatusSent;
|
bool m_spidStatusSent;
|
||||||
|
|
||||||
|
bool m_rotCtlDReadAz; //!< rotctrld returns 'p' responses over two lines
|
||||||
|
QString m_rotCtlDAz;
|
||||||
|
|
||||||
bool handleMessage(const Message& cmd);
|
bool handleMessage(const Message& cmd);
|
||||||
void applySettings(const GS232ControllerSettings& settings, bool force = false);
|
void applySettings(const GS232ControllerSettings& settings, bool force = false);
|
||||||
void openSerialPort(const GS232ControllerSettings& settings);
|
QIODevice *openSerialPort(const GS232ControllerSettings& settings);
|
||||||
|
QIODevice *openSocket(const GS232ControllerSettings& settings);
|
||||||
void setAzimuth(float azimuth);
|
void setAzimuth(float azimuth);
|
||||||
void setAzimuthElevation(float azimuth, float elevation);
|
void setAzimuthElevation(float azimuth, float elevation);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
void readSerialData();
|
void readData();
|
||||||
void update();
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<h1>GS-232 Rotator Controller Feature Plugin</h1>
|
<h1>Rotator Controller Feature Plugin</h1>
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
<h2>Introduction</h2>
|
||||||
|
|
||||||
The GS-232 Rotator Controller feature plugin allows SDRangel to send commands to GS-232 and SPID rotators. This allows SDRangel to point antennas mounted on a rotator to a specified azimuth and elevation.
|
The Rotator Controller feature plugin allows SDRangel to send commands to GS-232 and SPID rotators as well as hamlib's rotctld, via serial or TCP. 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 Map Feature, the ADS-B Demodulator, or the Star Tracker.
|
Azimuth and elevation can be set manually by a user in the GUI, via the REST API, or via another plugin, such as the Map Feature, the ADS-B Demodulator, or the Star Tracker.
|
||||||
|
|
||||||
<h2>Interface</h2>
|
<h2>Interface</h2>
|
||||||
|
|
||||||
![GS232 Rotator Controller feature plugin GUI](../../../doc/img/GS232Controller_plugin.png)
|
![Rotator Controller feature plugin GUI](../../../doc/img/GS232Controller_plugin.png)
|
||||||
|
|
||||||
<h3>1: Start/Stop plugin</h3>
|
<h3>1: Start/Stop plugin</h3>
|
||||||
|
|
||||||
@ -42,15 +42,11 @@ For example, the ADS-B plugin will display the flight number of the target aircr
|
|||||||
|
|
||||||
<h3>7: Protocol</h3>
|
<h3>7: Protocol</h3>
|
||||||
|
|
||||||
Selects which serial protocol to use. This can be GS-232 or SPID (rot2prog).
|
Selects which protocol to use. This can be GS-232, SPID (rot2prog) or rotctld.
|
||||||
|
|
||||||
<h3>8: Tolerance</h3>
|
<h3>8: Connection</h3>
|
||||||
|
|
||||||
Specifies a tolerance in degrees, below which, changes in target azimuth or elevation will not be sent to the rotator.
|
Selects whether to use a serial connection or TCP.
|
||||||
This can prevent some rotators that have a limited accuracy from making unbeneficial movements.
|
|
||||||
|
|
||||||
If this set to 0, every target azimuth and elevation received by the controller will be send to the rotator.
|
|
||||||
If it is set to 2, then a change in azimuth of +-1 degree from the previous azimuth, would not be sent to the rotator.
|
|
||||||
|
|
||||||
<h3>9: Serial Port</h3>
|
<h3>9: Serial Port</h3>
|
||||||
|
|
||||||
@ -60,25 +56,41 @@ Specifies the serial port (E.g. COM3 on Windows or /dev/ttyS0 on Linux) that wil
|
|||||||
|
|
||||||
Specifies the baud rate that will be used to send commands to the rotator. Typically this is 9600 for GS-232.
|
Specifies the baud rate that will be used to send commands to the rotator. Typically this is 9600 for GS-232.
|
||||||
|
|
||||||
<h3>11: Azimuth Offset</h3>
|
<h3>11: Host</h3>
|
||||||
|
|
||||||
|
Specifies the hostname / IP address of the computer running rotctld.
|
||||||
|
|
||||||
|
<h3>12: Port</h3>
|
||||||
|
|
||||||
|
Specifies the TCP port number rotctld is listening on.
|
||||||
|
|
||||||
|
<h3>13: Azimuth Offset</h3>
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<h3>12: Elevation Offset</h3>
|
<h3>14: Elevation Offset</h3>
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
<h3>13 and 14: Azimuth Min and Max</h3>
|
<h3>15 and 16: Azimuth Min and Max</h3>
|
||||||
|
|
||||||
The azimuth min and max values specify the minimum and maximum azimuth values (after offset has been applied), that will be sent to the rotator.
|
The azimuth min and max values specify the minimum and maximum azimuth values (after offset has been applied), that will be sent to the rotator.
|
||||||
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
|
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
|
||||||
|
|
||||||
<h3>15 and 16: Elevation Min and Max</h3>
|
<h3>17 and 18: Elevation Min and Max</h3>
|
||||||
|
|
||||||
The elevation min and max values specify the minimum and maximum elevation values (after offset has been applied), that will be sent to the rotator.
|
The elevation min and max values specify the minimum and maximum elevation values (after offset has been applied), that will be sent to the rotator.
|
||||||
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
|
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
|
||||||
If the maximum elevation is set to 0, the controller will only use the M GS-232 command, rather than M and W.
|
If the maximum elevation is set to 0, the controller will only use the M GS-232 command, rather than M and W.
|
||||||
|
|
||||||
|
<h3>19: Tolerance</h3>
|
||||||
|
|
||||||
|
Specifies a tolerance in degrees, below which, changes in target azimuth or elevation will not be sent to the rotator.
|
||||||
|
This can prevent some rotators that have a limited accuracy from making unbeneficial movements.
|
||||||
|
|
||||||
|
If this set to 0, every target azimuth and elevation received by the controller will be send to the rotator.
|
||||||
|
If it is set to 2, then a change in azimuth of +-1 degree from the previous azimuth, would not be sent to the rotator.
|
||||||
|
|
||||||
<h2>GS-232 Protocol Implementation</h2>
|
<h2>GS-232 Protocol Implementation</h2>
|
||||||
|
|
||||||
The controller uses the Waaa eee command when elevation needs to be set.
|
The controller uses the Waaa eee command when elevation needs to be set.
|
||||||
@ -92,6 +104,10 @@ The 0x1f status command is used to read current azimuth and elevation.
|
|||||||
A 12 byte response is expected for set and status commands.
|
A 12 byte response is expected for set and status commands.
|
||||||
All frames start with 0x57 and end with 0x20.
|
All frames start with 0x57 and end with 0x20.
|
||||||
|
|
||||||
|
<h2>rotctld Protocol Implementation</h2>
|
||||||
|
|
||||||
|
The controller uses the 'P' and 'p' commands to set and get azimuth and elevation.
|
||||||
|
|
||||||
<h2>API</h2>
|
<h2>API</h2>
|
||||||
|
|
||||||
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:
|
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:
|
||||||
|
Loading…
Reference in New Issue
Block a user