Add SPID rot2prog protocol support. Add tolerance setting.

pull/914/head
Jon Beniston 2021-05-30 12:38:07 +01:00
rodzic 1e5c4343d1
commit f51e8b4095
13 zmienionych plików z 572 dodań i 275 usunięć

Wyświetl plik

@ -216,6 +216,8 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, boo
<< " m_azimuthMax: " << settings.m_azimuthMax
<< " m_elevationMin: " << settings.m_elevationMin
<< " m_elevationMax: " << settings.m_elevationMax
<< " m_tolerance: " << settings.m_tolerance
<< " m_protocol: " << settings.m_protocol
<< " m_serialPort: " << settings.m_serialPort
<< " m_baudRate: " << settings.m_baudRate
<< " m_track: " << settings.m_track
@ -274,6 +276,12 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, boo
if ((m_settings.m_elevationMin != settings.m_elevationMin) || force) {
reverseAPIKeys.append("elevationMin");
}
if ((m_settings.m_tolerance != settings.m_tolerance) || force) {
reverseAPIKeys.append("tolerance");
}
if ((m_settings.m_protocol != settings.m_protocol) || force) {
reverseAPIKeys.append("m_protocol");
}
if ((m_settings.m_title != settings.m_title) || force) {
reverseAPIKeys.append("title");
}
@ -360,6 +368,8 @@ void GS232Controller::webapiFormatFeatureSettings(
response.getGs232ControllerSettings()->setAzimuthMax(settings.m_azimuthMax);
response.getGs232ControllerSettings()->setElevationMin(settings.m_elevationMin);
response.getGs232ControllerSettings()->setElevationMax(settings.m_elevationMax);
response.getGs232ControllerSettings()->setTolerance(settings.m_tolerance);
response.getGs232ControllerSettings()->setProtocol(settings.m_protocol);
if (response.getGs232ControllerSettings()->getTitle()) {
*response.getGs232ControllerSettings()->getTitle() = settings.m_title;
@ -420,6 +430,12 @@ void GS232Controller::webapiUpdateFeatureSettings(
if (featureSettingsKeys.contains("elevationMax")) {
settings.m_elevationMax = response.getGs232ControllerSettings()->getElevationMax();
}
if (featureSettingsKeys.contains("tolerance")) {
settings.m_tolerance = response.getGs232ControllerSettings()->getTolerance();
}
if (featureSettingsKeys.contains("protocol")) {
settings.m_protocol = (GS232ControllerSettings::Protocol)response.getGs232ControllerSettings()->getProtocol();
}
if (featureSettingsKeys.contains("title")) {
settings.m_title = *response.getGs232ControllerSettings()->getTitle();
}
@ -484,6 +500,12 @@ void GS232Controller::webapiReverseSendSettings(QList<QString>& featureSettingsK
if (featureSettingsKeys.contains("elevationMax") || force) {
swgGS232ControllerSettings->setElevationMax(settings.m_elevationMax);
}
if (featureSettingsKeys.contains("tolerance") || force) {
swgGS232ControllerSettings->setTolerance(settings.m_tolerance);
}
if (featureSettingsKeys.contains("protocol") || force) {
swgGS232ControllerSettings->setProtocol((int)settings.m_protocol);
}
if (featureSettingsKeys.contains("title") || force) {
swgGS232ControllerSettings->setTitle(new QString(settings.m_title));
}

Wyświetl plik

@ -94,8 +94,8 @@ bool GS232ControllerGUI::handleMessage(const Message& message)
else if (GS232ControllerReport::MsgReportAzAl::match(message))
{
GS232ControllerReport::MsgReportAzAl& azAl = (GS232ControllerReport::MsgReportAzAl&) message;
ui->azimuthCurrentText->setText(QString("%1").arg(round(azAl.getAzimuth())));
ui->elevationCurrentText->setText(QString("%1").arg(round(azAl.getElevation())));
ui->azimuthCurrentText->setText(QString("%1").arg(azAl.getAzimuth()));
ui->elevationCurrentText->setText(QString("%1").arg(azAl.getElevation()));
return true;
}
else if (MainCore::MsgTargetAzimuthElevation::match(message))
@ -153,6 +153,9 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
m_statusTimer.start(1000);
ui->azimuthCurrentText->setText("-");
ui->elevationCurrentText->setText("-");
updateSerialPortList();
displaySettings();
applySettings(true);
@ -175,6 +178,8 @@ void GS232ControllerGUI::displaySettings()
blockApplySettings(true);
ui->azimuth->setValue(m_settings.m_azimuth);
ui->elevation->setValue(m_settings.m_elevation);
ui->protocol->setCurrentIndex((int)m_settings.m_protocol);
updateDecimals(m_settings.m_protocol);
if (m_settings.m_serialPort.length() > 0)
ui->serialPort->lineEdit()->setText(m_settings.m_serialPort);
ui->baudRate->setCurrentText(QString("%1").arg(m_settings.m_baudRate));
@ -281,6 +286,27 @@ void GS232ControllerGUI::on_startStop_toggled(bool checked)
}
}
void GS232ControllerGUI::updateDecimals(GS232ControllerSettings::Protocol protocol)
{
if (protocol == GS232ControllerSettings::GS232)
{
ui->azimuth->setDecimals(0);
ui->elevation->setDecimals(0);
}
else
{
ui->azimuth->setDecimals(1);
ui->elevation->setDecimals(1);
}
}
void GS232ControllerGUI::on_protocol_currentIndexChanged(int index)
{
m_settings.m_protocol = (GS232ControllerSettings::Protocol)index;
updateDecimals(m_settings.m_protocol);
applySettings();
}
void GS232ControllerGUI::on_serialPort_currentIndexChanged(int index)
{
(void) index;
@ -295,16 +321,16 @@ void GS232ControllerGUI::on_baudRate_currentIndexChanged(int index)
applySettings();
}
void GS232ControllerGUI::on_azimuth_valueChanged(int value)
void GS232ControllerGUI::on_azimuth_valueChanged(double value)
{
m_settings.m_azimuth = value;
m_settings.m_azimuth = (float)value;
ui->targetName->setText("");
applySettings();
}
void GS232ControllerGUI::on_elevation_valueChanged(int value)
void GS232ControllerGUI::on_elevation_valueChanged(double value)
{
m_settings.m_elevation = value;
m_settings.m_elevation = (float)value;
ui->targetName->setText("");
applySettings();
}
@ -345,6 +371,12 @@ void GS232ControllerGUI::on_elevationMax_valueChanged(int value)
applySettings();
}
void GS232ControllerGUI::on_tolerance_valueChanged(int value)
{
m_settings.m_tolerance = value;
applySettings();
}
void GS232ControllerGUI::on_track_stateChanged(int state)
{
m_settings.m_track = state == Qt::Checked;

Wyświetl plik

@ -64,6 +64,7 @@ private:
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void updateDecimals(GS232ControllerSettings::Protocol protocol);
void updatePipeList();
void updateSerialPortList();
bool handleMessage(const Message& message);
@ -76,11 +77,12 @@ private slots:
void onWidgetRolled(QWidget* widget, bool rollDown);
void handleInputMessages();
void on_startStop_toggled(bool checked);
void on_protocol_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_azimuth_valueChanged(double value);
void on_elevation_valueChanged(double value);
void on_targets_currentTextChanged(const QString& text);
void on_azimuthOffset_valueChanged(int value);
void on_elevationOffset_valueChanged(int value);
@ -88,8 +90,8 @@ private slots:
void on_azimuthMax_valueChanged(int value);
void on_elevationMin_valueChanged(int value);
void on_elevationMax_valueChanged(int value);
void on_tolerance_valueChanged(int value);
void updateStatus();
};
#endif // INCLUDE_FEATURE_GS232CONTROLLERGUI_H_

Wyświetl plik

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>223</height>
<width>360</width>
<height>231</height>
</rect>
</property>
<property name="sizePolicy">
@ -18,13 +18,13 @@
</property>
<property name="minimumSize">
<size>
<width>320</width>
<width>360</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>350</width>
<width>360</width>
<height>16777215</height>
</size>
</property>
@ -42,8 +42,8 @@
<rect>
<x>10</x>
<y>10</y>
<width>331</width>
<height>191</height>
<width>341</width>
<height>211</height>
</rect>
</property>
<property name="windowTitle">
@ -70,7 +70,7 @@
<item>
<widget class="ButtonSwitch" name="startStop">
<property name="toolTip">
<string>start/stop acquisition</string>
<string>Start/stop controller</string>
</property>
<property name="text">
<string/>
@ -103,18 +103,18 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="azimuth">
<widget class="QDoubleSpinBox" name="azimuth">
<property name="toolTip">
<string>Target azimuth in degrees</string>
</property>
<property name="minimum">
<number>0</number>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<number>450</number>
<double>450.000000000000000</double>
</property>
<property name="value">
<number>359</number>
<double>360.000000000000000</double>
</property>
</widget>
</item>
@ -122,7 +122,7 @@
<widget class="QLabel" name="azimuthCurrentText">
<property name="minimumSize">
<size>
<width>23</width>
<width>32</width>
<height>0</height>
</size>
</property>
@ -130,7 +130,7 @@
<string>Current azimuth in degrees</string>
</property>
<property name="text">
<string>-</string>
<string>360.0</string>
</property>
</widget>
</item>
@ -149,15 +149,18 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="elevation">
<widget class="QDoubleSpinBox" name="elevation">
<property name="toolTip">
<string>Target elevation in degrees</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<number>180</number>
<double>180.000000000000000</double>
</property>
<property name="value">
<number>180</number>
<double>180.000000000000000</double>
</property>
</widget>
</item>
@ -165,7 +168,7 @@
<widget class="QLabel" name="elevationCurrentText">
<property name="minimumSize">
<size>
<width>22</width>
<width>32</width>
<height>0</height>
</size>
</property>
@ -173,75 +176,7 @@
<string>Current elevation in degrees</string>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="localDeviceLayout">
<item>
<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>
<widget class="QLabel" name="targetsLabel">
<property name="text">
<string>Source</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="targets">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Target to track</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="channelLayout">
<item>
<widget class="QLabel" name="targetNameLabel">
<property name="text">
<string>Target</string>
</property>
</widget>
</item>
<item>
<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>
<string>180.0</string>
</property>
</widget>
</item>
@ -249,49 +184,60 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QLabel" name="baudRateLabel">
<item row="2" column="2">
<widget class="QLabel" name="toleranceLabel">
<property name="text">
<string>Baud rate</string>
<string>Tolerance</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="azimuthOffsetLabel">
<property name="text">
<string>Azimuth offset</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="azimuthOffset">
<property name="toolTip">
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
</property>
<property name="minimum">
<number>-360</number>
</property>
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QSpinBox" name="elevationOffset">
<property name="toolTip">
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
</property>
<property name="minimum">
<number>-180</number>
</property>
<property name="maximum">
<number>180</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="elevationMin">
<property name="maximum">
<number>180</number>
<widget class="QComboBox" name="serialPort">
<property name="toolTip">
<string>Name of serial port to use to connect to the GS-232 controller</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="elevationMinLabel">
<property name="text">
<string>Elevation min</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="azimuthMinLabel">
<property name="text">
<string>Azimuth min</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="elevationMaxLabel">
<property name="text">
<string>Elevation max</string>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QSpinBox" name="elevationMax">
<property name="maximum">
<number>180</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="baudRate">
<property name="toolTip">
<string>Serial port baud rate for the GS-232 controller</string>
@ -351,84 +297,158 @@
</item>
</widget>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="azimuthMax">
<property name="maximum">
<number>450</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="azimuthMin">
<property name="maximum">
<number>450</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="serialPort">
<property name="toolTip">
<string>Name of serial port to use to connect to the GS-232 controller</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="3" column="0">
<widget class="QLabel" name="serialLabel">
<property name="text">
<string>Serial Port</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="azimuthMaxLabel">
<property name="text">
<string>Azimuth max</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="azimuthOffsetLabel">
<property name="text">
<string>Azimuth offset</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="azimuthOffset">
<property name="toolTip">
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
</property>
<property name="minimum">
<number>-360</number>
</property>
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
<item row="1" column="2">
<item row="4" column="2">
<widget class="QLabel" name="elevationOffsetLabel">
<property name="text">
<string>Elevation offset</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="elevationOffset">
<property name="toolTip">
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
</property>
<property name="minimum">
<number>-180</number>
<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>
<property name="singleStep">
<number>1</number>
</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="3">
<widget class="QSpinBox" name="tolerance">
<property name="toolTip">
<string>Tolerance in degrees</string>
</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">
<property name="text">
<string>Azimuth max</string>
</property>
</widget>
</item>
<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="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="targets">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Target to track</string>
</property>
</widget>
</item>
@ -454,9 +474,6 @@
<tabstop>startStop</tabstop>
<tabstop>azimuth</tabstop>
<tabstop>elevation</tabstop>
<tabstop>track</tabstop>
<tabstop>targets</tabstop>
<tabstop>targetName</tabstop>
<tabstop>serialPort</tabstop>
<tabstop>baudRate</tabstop>
<tabstop>azimuthOffset</tabstop>

Wyświetl plik

@ -30,7 +30,7 @@
const PluginDescriptor GS232ControllerPlugin::m_pluginDescriptor = {
GS232Controller::m_featureId,
QStringLiteral("GS-232 Rotator Controller"),
QStringLiteral("6.13.0"),
QStringLiteral("6.13.1"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

Wyświetl plik

@ -44,8 +44,8 @@ GS232ControllerSettings::GS232ControllerSettings()
void GS232ControllerSettings::resetToDefaults()
{
m_azimuth = 0;
m_elevation = 0;
m_azimuth = 0.0f;
m_elevation = 0.0f;
m_serialPort = "";
m_baudRate = 9600;
m_track = false;
@ -63,14 +63,16 @@ void GS232ControllerSettings::resetToDefaults()
m_azimuthMax = 450;
m_elevationMin = 0;
m_elevationMax = 180;
m_tolerance = 0;
m_protocol = GS232;
}
QByteArray GS232ControllerSettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_azimuth);
s.writeS32(2, m_elevation);
s.writeFloat(1, m_azimuth);
s.writeFloat(2, m_elevation);
s.writeString(3, m_serialPort);
s.writeS32(4, m_baudRate);
s.writeBool(5, m_track);
@ -88,6 +90,8 @@ QByteArray GS232ControllerSettings::serialize() const
s.writeS32(18, m_azimuthMax);
s.writeS32(19, m_elevationMin);
s.writeS32(20, m_elevationMax);
s.writeS32(21, m_tolerance);
s.writeS32(22, (int)m_protocol);
return s.final();
}
@ -108,8 +112,8 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
uint32_t utmp;
QString strtmp;
d.readS32(1, &m_azimuth, 0);
d.readS32(2, &m_elevation, 0);
d.readFloat(1, &m_azimuth, 0);
d.readFloat(2, &m_elevation, 0);
d.readString(3, &m_serialPort, "");
d.readS32(4, &m_baudRate, 9600);
d.readBool(5, &m_track, false);
@ -136,6 +140,8 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
d.readS32(18, &m_azimuthMax, 450);
d.readS32(19, &m_elevationMin, 0);
d.readS32(20, &m_elevationMax, 180);
d.readS32(21, &m_tolerance, 0);
d.readS32(22, (int*)&m_protocol, GS232);
return true;
}

Wyświetl plik

@ -28,8 +28,8 @@ class Serializable;
struct GS232ControllerSettings
{
int m_azimuth;
int m_elevation;
float m_azimuth;
float m_elevation;
QString m_serialPort;
int m_baudRate;
bool m_track;
@ -40,6 +40,8 @@ struct GS232ControllerSettings
int m_azimuthMax;
int m_elevationMin;
int m_elevationMax;
int m_tolerance;
enum Protocol { GS232, SPID } m_protocol;
QString m_title;
quint32 m_rgbColor;
bool m_useReverseAPI;

Wyświetl plik

@ -38,8 +38,11 @@ GS232ControllerWorker::GS232ControllerWorker() :
m_msgQueueToGUI(nullptr),
m_running(false),
m_mutex(QMutex::Recursive),
m_lastAzimuth(-1),
m_lastElevation(-1)
m_lastAzimuth(-1.0f),
m_lastElevation(-1.0f),
m_spidSetOutstanding(false),
m_spidSetSent(false),
m_spidStatusSent(false)
{
connect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(update()));
m_pollTimer.start(1000);
@ -54,6 +57,11 @@ void GS232ControllerWorker::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_inputMessageQueue.clear();
m_lastAzimuth = -1.0f;
m_lastElevation = -1.0f;
m_spidSetOutstanding = false;
m_spidSetSent = false;
m_spidStatusSent = false;
}
bool GS232ControllerWorker::startWork()
@ -61,7 +69,9 @@ bool GS232ControllerWorker::startWork()
QMutexLocker mutexLocker(&m_mutex);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
connect(&m_serialPort, &QSerialPort::readyRead, this, &GS232ControllerWorker::readSerialData);
openSerialPort(m_settings);
if (!m_settings.m_serialPort.isEmpty()) {
openSerialPort(m_settings);
}
m_running = true;
return m_running;
}
@ -116,6 +126,8 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
<< " m_azimuthMax: " << settings.m_azimuthMax
<< " m_elevationMin: " << settings.m_elevationMin
<< " m_elevationMax: " << settings.m_elevationMax
<< " m_tolerance: " << settings.m_tolerance
<< " m_protocol: " << settings.m_protocol
<< " m_serialPort: " << settings.m_serialPort
<< " m_baudRate: " << settings.m_baudRate
<< " force: " << force;
@ -131,21 +143,25 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
// Apply offset then clamp
int azimuth = settings.m_azimuth;
float azimuth = settings.m_azimuth;
azimuth += settings.m_azimuthOffset;
azimuth = std::max(azimuth, settings.m_azimuthMin);
azimuth = std::min(azimuth, settings.m_azimuthMax);
azimuth = std::max(azimuth, (float)settings.m_azimuthMin);
azimuth = std::min(azimuth, (float)settings.m_azimuthMax);
int elevation = settings.m_elevation;
float elevation = settings.m_elevation;
elevation += settings.m_elevationOffset;
elevation = std::max(elevation, settings.m_elevationMin);
elevation = std::min(elevation, settings.m_elevationMax);
elevation = std::max(elevation, (float)settings.m_elevationMin);
elevation = std::min(elevation, (float)settings.m_elevationMax);
if (((elevation != m_lastElevation) || force) && (settings.m_elevationMax != 0))
// Don't set if within tolerance of last setting
float azDiff = std::abs(azimuth - m_lastAzimuth);
float elDiff = std::abs(elevation - m_lastElevation);
if (((elDiff > settings.m_tolerance) || (m_lastElevation == -1) || force) && (settings.m_elevationMax != 0))
{
setAzimuthElevation(azimuth, elevation);
}
else if ((azimuth != m_lastAzimuth) || force)
else if ((azDiff > settings.m_tolerance) || (m_lastAzimuth == -1) || force)
{
setAzimuth(azimuth);
}
@ -155,35 +171,81 @@ void GS232ControllerWorker::applySettings(const GS232ControllerSettings& setting
void GS232ControllerWorker::openSerialPort(const GS232ControllerSettings& settings)
{
if (m_serialPort.isOpen())
if (m_serialPort.isOpen()) {
m_serialPort.close();
}
m_serialPort.setPortName(settings.m_serialPort);
m_serialPort.setBaudRate(settings.m_baudRate);
if (!m_serialPort.open(QIODevice::ReadWrite))
{
qCritical() << "GS232ControllerWorker::openSerialPort: Failed to open serial port " << settings.m_serialPort << ". Error: " << m_serialPort.error();
if (m_msgQueueToFeature)
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_lastAzimuth = -1;
m_lastElevation = -1;
}
void GS232ControllerWorker::setAzimuth(int azimuth)
void GS232ControllerWorker::setAzimuth(float azimuth)
{
QString cmd = QString("M%1\r\n").arg(azimuth, 3, 10, QLatin1Char('0'));
QByteArray data = cmd.toLatin1();
m_serialPort.write(data);
m_lastAzimuth = azimuth;
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
{
QString cmd = QString("M%1\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0'));
QByteArray data = cmd.toLatin1();
m_serialPort.write(data);
}
else
{
setAzimuthElevation(azimuth, m_lastElevation);
}
m_lastAzimuth = azimuth;
}
void GS232ControllerWorker::setAzimuthElevation(int azimuth, int elevation)
void GS232ControllerWorker::setAzimuthElevation(float azimuth, float elevation)
{
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);
m_lastAzimuth = azimuth;
m_lastElevation = elevation;
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
{
QString cmd = QString("W%1 %2\r\n").arg((int)std::round(azimuth), 3, 10, QLatin1Char('0')).arg((int)std::round(elevation), 3, 10, QLatin1Char('0'));
QByteArray data = cmd.toLatin1();
m_serialPort.write(data);
}
else
{
qDebug() << "GS232ControllerWorker::setAzimuthElevation " << " AZ " << azimuth << " EL " << elevation;
if (!m_spidSetSent && !m_spidStatusSent)
{
QByteArray cmd(13, (char)0);
cmd[0] = 0x57; // Start
int h = std::round((azimuth + 360.0f) * 2.0f);
cmd[1] = 0x30 | (h / 1000);
cmd[2] = 0x30 | ((h % 1000) / 100);
cmd[3] = 0x30 | ((h % 100) / 10);
cmd[4] = 0x30 | (h % 10);
cmd[5] = 2; // 2 degree per impulse
int v = std::round((elevation + 360.0f) * 2.0f);
cmd[6] = 0x30 | (v / 1000);
cmd[7] = 0x30 | ((v % 1000) / 100);
cmd[8] = 0x30 | ((v % 100) / 10);
cmd[9] = 0x30 | (v % 10);
cmd[10] = 2; // 2 degree per impulse
cmd[11] = 0x2f; // Set cmd
cmd[12] = 0x20; // End
m_serialPort.write(cmd);
m_spidSetSent = true;
}
else
{
qDebug() << "GS232ControllerWorker::setAzimuthElevation: Not sent, waiting for status reply";
m_spidSetOutstanding = true;
}
}
m_lastAzimuth = azimuth;
m_lastElevation = elevation;
}
void GS232ControllerWorker::readSerialData()
@ -191,32 +253,77 @@ void GS232ControllerWorker::readSerialData()
char buf[1024];
qint64 len;
while (m_serialPort.canReadLine())
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
{
len = m_serialPort.readLine(buf, sizeof(buf));
if (len != -1)
while (m_serialPort.canReadLine())
{
QString response = QString::fromUtf8(buf, len);
// MD-02 can return AZ=-00 EL=-00 and other negative angles
QRegularExpression re("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)");
QRegularExpressionMatch match = re.match(response);
if (match.hasMatch())
len = m_serialPort.readLine(buf, sizeof(buf));
if (len != -1)
{
QString az = match.captured(1);
QString el = match.captured(2);
//qDebug() << "GS232ControllerWorker::readSerialData read az " << az << " el " << el;
if (getMessageQueueToGUI())
getMessageQueueToGUI()->push( GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
QString response = QString::fromUtf8(buf, len);
// MD-02 can return AZ=-00 EL=-00 and other negative angles
QRegularExpression re("AZ=([-\\d]\\d\\d) *EL=([-\\d]\\d\\d)");
QRegularExpressionMatch match = re.match(response);
if (match.hasMatch())
{
QString az = match.captured(1);
QString el = match.captured(2);
//qDebug() << "GS232ControllerWorker::readSerialData read Az " << az << " El " << el;
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push( GS232ControllerReport::MsgReportAzAl::create(az.toFloat(), el.toFloat()));
}
}
else if (response == "\r\n")
{
// Ignore
}
else
{
qDebug() << "GS232ControllerWorker::readSerialData - unexpected GS-232 response \"" << response << "\"";
if (m_msgQueueToFeature) {
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 response: %1").arg(response)));
}
}
}
else if (response == "\r\n")
}
}
else
{
while (m_serialPort.bytesAvailable() >= 12)
{
len = m_serialPort.read(buf, 12);
if ((len == 12) && (buf[0] == 0x57))
{
// Ignore
double az;
double el;
az = buf[1] * 100.0 + buf[2] * 10.0 + buf[3] + buf[4] / 10.0 - 360.0;
el = buf[6] * 100.0 + buf[7] * 10.0 + buf[8] + buf[9] / 10.0 - 360.0;
//qDebug() << "GS232ControllerWorker::readSerialData read Az " << az << " El " << el;
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push( GS232ControllerReport::MsgReportAzAl::create(az, el));
}
if (m_spidStatusSent && m_spidSetSent) {
qDebug() << "GS232ControllerWorker::readSerialData - m_spidStatusSent and m_spidSetSent set simultaneously";
}
if (m_spidStatusSent) {
m_spidStatusSent = false;
}
if (m_spidSetSent) {
m_spidSetSent = false;
}
if (m_spidSetOutstanding)
{
m_spidSetOutstanding = false;
setAzimuthElevation(m_lastAzimuth, m_lastElevation);
}
}
else
{
qDebug() << "GS232ControllerWorker::readSerialData - unexpected response \"" << response << "\"";
if (m_msgQueueToFeature)
m_msgQueueToFeature->push(GS232Controller::MsgReportWorker::create(QString("Unexpected GS-232 serial response: %1").arg(response)));
QByteArray bytes(buf, (int)len);
qDebug() << "GS232ControllerWorker::readSerialData - 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())));
}
}
}
}
@ -227,7 +334,27 @@ void GS232ControllerWorker::update()
// Request current Az/El from GS-232 controller
if (m_serialPort.isOpen())
{
QByteArray cmd("C2\r\n");
m_serialPort.write(cmd);
if (m_settings.m_protocol == GS232ControllerSettings::GS232)
{
QByteArray cmd("C2\r\n");
m_serialPort.write(cmd);
}
else
{
// Don't send a new status command, if waiting for a previous reply
if (!m_spidSetSent && !m_spidStatusSent)
{
// Status
QByteArray cmd;
cmd.append((char)0x57); // Start
for (int i = 0; i < 10; i++) {
cmd.append((char)0x0);
}
cmd.append((char)0x1f); // Status
cmd.append((char)0x20); // End
m_serialPort.write(cmd);
m_spidStatusSent = true;
}
}
}
}

Wyświetl plik

@ -76,15 +76,19 @@ private:
QSerialPort m_serialPort;
QTimer m_pollTimer;
int m_lastAzimuth;
int m_lastElevation;
float m_lastAzimuth;
float m_lastElevation;
bool m_spidSetOutstanding;
bool m_spidSetSent;
bool m_spidStatusSent;
bool handleMessage(const Message& cmd);
void applySettings(const GS232ControllerSettings& settings, bool force = false);
MessageQueue *getMessageQueueToGUI() { return m_msgQueueToGUI; }
void openSerialPort(const GS232ControllerSettings& settings);
void setAzimuth(int azimuth);
void setAzimuthElevation(int azimuth, int elevation);
void setAzimuth(float azimuth);
void setAzimuthElevation(float azimuth, float elevation);
private slots:
void handleInputMessages();

Wyświetl plik

@ -38,28 +38,40 @@ Specify the SDRangel Channel or Feature that that will control the target aziumt
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.
<h3>7: Serial Port</h3>
<h3>7: Protocol</h3>
Selects which serial protocol to use. This can be GS-232 or SPID (rot2prog).
<h3>8: 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.
<h3>9: Serial Port</h3>
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.
<h3>8: Baud rate</h3>
<h3>10: Baud rate</h3>
Specifies the baud rate that will be used to send commands to the GS-232 rotator. Typically this is 9600.
<h3>9: Azimuth Offset</h3>
<h3>11: 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.
<h3>10: Elevation Offset</h3>
<h3>12: 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.
<h3>11 and 12: Azimuth Min and Max</h3>
<h3>13 and 14: 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.
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
<h3>13 and 14: Elevation Min and Max</h3>
<h3>15 and 16: 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.
These values can be used to prevent the rotator from rotating an antenna in to an obstable.
@ -71,6 +83,13 @@ The controller uses the Waaa eee command when elevation needs to be set.
When only azimuth needs to be set, the Maaa command is used.
The C2 command is used to read current azimuth and elevation. A response of AZ=aaaEL=eee is expected.
<h2>SPID rot2prog Protocol Implementation</h2>
The controller uses the 0x2f set command with PH/PV=2 to set azimuth and elevation.
The 0x1f status command is used to read current azimuth and elevation.
A 12 byte response is expected for set and status commands.
All frames start with 0x57 and end with 0x20.
<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:

Wyświetl plik

@ -3,10 +3,12 @@ GS232ControllerSettings:
properties:
azimuth:
description: Target azimuth in degrees (0-450)
type: integer
type: number
format: float
elevation:
description: Target elevation in degrees (0-180)
type: integer
type: number
format: float
serialPort:
description: The serial port the GS-232 controller is connected to
type: string
@ -37,6 +39,12 @@ GS232ControllerSettings:
elevationMax:
description: Maximum elevation the controller will output
type: integer
tolerance:
description: Tolerance in degrees
type: integer
protocol:
description: (0 GS-232, 1 SPID rot2prog)
type: integer
title:
type: string
rgbColor:

Wyświetl plik

@ -28,9 +28,9 @@ SWGGS232ControllerSettings::SWGGS232ControllerSettings(QString* json) {
}
SWGGS232ControllerSettings::SWGGS232ControllerSettings() {
azimuth = 0;
azimuth = 0.0f;
m_azimuth_isSet = false;
elevation = 0;
elevation = 0.0f;
m_elevation_isSet = false;
serial_port = nullptr;
m_serial_port_isSet = false;
@ -52,6 +52,10 @@ SWGGS232ControllerSettings::SWGGS232ControllerSettings() {
m_elevation_min_isSet = false;
elevation_max = 0;
m_elevation_max_isSet = false;
tolerance = 0;
m_tolerance_isSet = false;
protocol = 0;
m_protocol_isSet = false;
title = nullptr;
m_title_isSet = false;
rgb_color = 0;
@ -74,9 +78,9 @@ SWGGS232ControllerSettings::~SWGGS232ControllerSettings() {
void
SWGGS232ControllerSettings::init() {
azimuth = 0;
azimuth = 0.0f;
m_azimuth_isSet = false;
elevation = 0;
elevation = 0.0f;
m_elevation_isSet = false;
serial_port = new QString("");
m_serial_port_isSet = false;
@ -98,6 +102,10 @@ SWGGS232ControllerSettings::init() {
m_elevation_min_isSet = false;
elevation_max = 0;
m_elevation_max_isSet = false;
tolerance = 0;
m_tolerance_isSet = false;
protocol = 0;
m_protocol_isSet = false;
title = new QString("");
m_title_isSet = false;
rgb_color = 0;
@ -132,6 +140,8 @@ SWGGS232ControllerSettings::cleanup() {
if(title != nullptr) {
delete title;
}
@ -156,9 +166,9 @@ SWGGS232ControllerSettings::fromJson(QString &json) {
void
SWGGS232ControllerSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&azimuth, pJson["azimuth"], "qint32", "");
::SWGSDRangel::setValue(&azimuth, pJson["azimuth"], "float", "");
::SWGSDRangel::setValue(&elevation, pJson["elevation"], "qint32", "");
::SWGSDRangel::setValue(&elevation, pJson["elevation"], "float", "");
::SWGSDRangel::setValue(&serial_port, pJson["serialPort"], "QString", "QString");
@ -180,6 +190,10 @@ SWGGS232ControllerSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&elevation_max, pJson["elevationMax"], "qint32", "");
::SWGSDRangel::setValue(&tolerance, pJson["tolerance"], "qint32", "");
::SWGSDRangel::setValue(&protocol, pJson["protocol"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
@ -246,6 +260,12 @@ SWGGS232ControllerSettings::asJsonObject() {
if(m_elevation_max_isSet){
obj->insert("elevationMax", QJsonValue(elevation_max));
}
if(m_tolerance_isSet){
obj->insert("tolerance", QJsonValue(tolerance));
}
if(m_protocol_isSet){
obj->insert("protocol", QJsonValue(protocol));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
@ -271,22 +291,22 @@ SWGGS232ControllerSettings::asJsonObject() {
return obj;
}
qint32
float
SWGGS232ControllerSettings::getAzimuth() {
return azimuth;
}
void
SWGGS232ControllerSettings::setAzimuth(qint32 azimuth) {
SWGGS232ControllerSettings::setAzimuth(float azimuth) {
this->azimuth = azimuth;
this->m_azimuth_isSet = true;
}
qint32
float
SWGGS232ControllerSettings::getElevation() {
return elevation;
}
void
SWGGS232ControllerSettings::setElevation(qint32 elevation) {
SWGGS232ControllerSettings::setElevation(float elevation) {
this->elevation = elevation;
this->m_elevation_isSet = true;
}
@ -391,6 +411,26 @@ SWGGS232ControllerSettings::setElevationMax(qint32 elevation_max) {
this->m_elevation_max_isSet = true;
}
qint32
SWGGS232ControllerSettings::getTolerance() {
return tolerance;
}
void
SWGGS232ControllerSettings::setTolerance(qint32 tolerance) {
this->tolerance = tolerance;
this->m_tolerance_isSet = true;
}
qint32
SWGGS232ControllerSettings::getProtocol() {
return protocol;
}
void
SWGGS232ControllerSettings::setProtocol(qint32 protocol) {
this->protocol = protocol;
this->m_protocol_isSet = true;
}
QString*
SWGGS232ControllerSettings::getTitle() {
return title;
@ -502,6 +542,12 @@ SWGGS232ControllerSettings::isSet(){
if(m_elevation_max_isSet){
isObjectUpdated = true; break;
}
if(m_tolerance_isSet){
isObjectUpdated = true; break;
}
if(m_protocol_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}

Wyświetl plik

@ -42,11 +42,11 @@ public:
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGGS232ControllerSettings* fromJson(QString &jsonString) override;
qint32 getAzimuth();
void setAzimuth(qint32 azimuth);
float getAzimuth();
void setAzimuth(float azimuth);
qint32 getElevation();
void setElevation(qint32 elevation);
float getElevation();
void setElevation(float elevation);
QString* getSerialPort();
void setSerialPort(QString* serial_port);
@ -78,6 +78,12 @@ public:
qint32 getElevationMax();
void setElevationMax(qint32 elevation_max);
qint32 getTolerance();
void setTolerance(qint32 tolerance);
qint32 getProtocol();
void setProtocol(qint32 protocol);
QString* getTitle();
void setTitle(QString* title);
@ -103,10 +109,10 @@ public:
virtual bool isSet() override;
private:
qint32 azimuth;
float azimuth;
bool m_azimuth_isSet;
qint32 elevation;
float elevation;
bool m_elevation_isSet;
QString* serial_port;
@ -139,6 +145,12 @@ private:
qint32 elevation_max;
bool m_elevation_max_isSet;
qint32 tolerance;
bool m_tolerance_isSet;
qint32 protocol;
bool m_protocol_isSet;
QString* title;
bool m_title_isSet;