Moved APRSIS reporting into its own background thread to avoid hangups. Added ability to turn off APRSIS reporting

This commit is contained in:
Jordan Sherer 2020-03-31 15:22:48 -04:00
parent ab339e9728
commit f087c0e3df
6 changed files with 89 additions and 26 deletions

View File

@ -20,6 +20,13 @@ public:
static QString stripSSID(QString call);
static QString replaceCallsignSuffixWithSSID(QString call, QString base);
bool isPasscodeValid(){ return m_localPasscode == QString::number(hashCallsign(m_localCall)); }
void enqueueRaw(QString aprsFrame);
void processQueue(bool disconnect=true);
public slots:
void setServer(QString host, quint16 port){
if(state() == QTcpSocket::ConnectedState){
disconnectFromHost();
@ -40,15 +47,9 @@ public:
m_localPasscode = passcode;
}
bool isPasscodeValid(){ return m_localPasscode == QString::number(hashCallsign(m_localCall)); }
void enqueueSpot(QString by_call, QString from_call, QString grid, QString comment);
void enqueueThirdParty(QString by_call, QString from_call, QString text);
void enqueueRaw(QString aprsFrame);
void processQueue(bool disconnect=true);
public slots:
void sendReports(){
if(m_paused) return;

View File

@ -434,6 +434,8 @@ private:
void delete_stations ();
void insert_station ();
Q_SLOT void on_psk_reporter_check_box_toggled(bool checked);
Q_SLOT void on_enable_aprs_spotting_check_box_toggled(bool checked);
Q_SLOT void on_notifications_check_box_toggled(bool checked);
Q_SLOT void on_font_push_button_clicked ();
Q_SLOT void on_tableFontButton_clicked();
@ -640,6 +642,7 @@ private:
bool id_after_73_;
bool tx_qsy_allowed_;
bool spot_to_reporting_networks_;
bool spot_to_aprs_;
bool transmit_directed_;
bool autoreply_on_at_startup_;
bool autoreply_confirmation_;
@ -801,6 +804,11 @@ void Configuration::set_spot_to_reporting_networks (bool spot)
}
}
bool Configuration::spot_to_aprs() const
{
return spot_to_reporting_networks() && m_->spot_to_aprs_;
}
bool Configuration::transmit_directed() const { return m_->transmit_directed_; }
bool Configuration::autoreply_on_at_startup () const {
// auto-reply cannot be on at startup if the callsign or grid is empty
@ -1544,6 +1552,7 @@ void Configuration::impl::initialize_models ()
ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
ui_->tx_qsy_check_box->setChecked (tx_qsy_allowed_);
ui_->psk_reporter_check_box->setChecked (spot_to_reporting_networks_);
ui_->enable_aprs_spotting_check_box->setChecked(spot_to_aprs_);
ui_->transmit_directed_check_box->setChecked(transmit_directed_);
ui_->autoreply_on_check_box->setChecked (autoreply_on_at_startup_);
ui_->autoreply_confirmation_check_box->setChecked (autoreply_confirmation_);
@ -1974,6 +1983,7 @@ void Configuration::impl::read_settings ()
monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
spot_to_reporting_networks_ = settings_->value ("PSKReporter", true).toBool ();
spot_to_aprs_ = settings_->value("SpotToAPRS", true).toBool();
write_logs_ = settings_->value("WriteLogs", true).toBool();
reset_activity_ = settings_->value("ResetActivity", false).toBool();
check_for_updates_ = settings_->value("CheckForUpdates", true).toBool();
@ -2189,6 +2199,7 @@ void Configuration::impl::write_settings ()
settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
settings_->setValue ("MonitorLastUsed", monitor_last_used_);
settings_->setValue ("PSKReporter", spot_to_reporting_networks_);
settings_->setValue ("SpotToAPRS", spot_to_aprs_);
settings_->setValue ("WriteLogs", write_logs_);
settings_->setValue ("ResetActivity", reset_activity_);
settings_->setValue ("CheckForUpdates", check_for_updates_);
@ -2803,6 +2814,7 @@ void Configuration::impl::accept ()
callsign_aging_ = ui_->callsign_aging_spin_box->value();
activity_aging_ = ui_->activity_aging_spin_box->value();
spot_to_reporting_networks_ = ui_->psk_reporter_check_box->isChecked ();
spot_to_aprs_ = ui_->enable_aprs_spotting_check_box->isChecked();
id_interval_ = ui_->CW_id_interval_spin_box->value ();
ntrials_ = ui_->sbNtrials->value ();
txDelay_ = ui_->sbTxDelay->value ();
@ -2969,6 +2981,19 @@ void Configuration::impl::reject ()
QDialog::reject ();
}
void Configuration::impl::on_psk_reporter_check_box_toggled(bool checked){
ui_->enable_aprs_spotting_check_box->setEnabled(checked);
bool spot = ui_->enable_aprs_spotting_check_box->isChecked();
ui_->aprs_server_line_edit->setEnabled(spot && checked);
ui_->aprs_server_port_spin_box->setEnabled(spot && checked);
}
void Configuration::impl::on_enable_aprs_spotting_check_box_toggled(bool checked){
ui_->aprs_server_line_edit->setEnabled(checked);
ui_->aprs_server_port_spin_box->setEnabled(checked);
}
void Configuration::impl::on_notifications_check_box_toggled(bool checked){
ui_->notifications_table_widget->setEnabled(checked);
}

View File

@ -138,6 +138,7 @@ public:
bool tx_qsy_allowed () const;
bool spot_to_reporting_networks () const;
void set_spot_to_reporting_networks (bool);
bool spot_to_aprs() const;
bool transmit_directed() const;
bool autoreply_on_at_startup () const;
bool autoreply_confirmation () const;

View File

@ -2368,9 +2368,9 @@ both here.</string>
<property name="geometry">
<rect>
<x>0</x>
<y>-60</y>
<y>0</y>
<width>746</width>
<height>682</height>
<height>667</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_30">
@ -2618,23 +2618,24 @@ This is used for reverse ping analysis which is very useful
for assessing propagation and system performance.</string>
</property>
<property name="text">
<string>Enable spotting to reporting networks (JS8NET, APRSIS, PSKReporter, etc)</string>
<string>Enable spotting to reporting networks (JS8NET, PSKReporter, etc)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>APRSIS Spotting</string>
</property>
<layout class="QFormLayout" name="formLayout_18">
<item row="0" column="0">
<item row="1" column="0">
<widget class="QCheckBox" name="enable_aprs_spotting_check_box">
<property name="text">
<string>Enable spotting @APRSIS messages to the APRS-IS network</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QFormLayout" name="formLayout_17">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>

View File

@ -480,6 +480,18 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
// notification audio operates in its own thread at a lower priority
m_notification->moveToThread(&m_notificationAudioThread);
// move the aprs client to its own network thread at a lower priority
m_aprsClient->moveToThread(&m_networkThread);
// hook up the aprs client slots and signals and disposal
connect (this, &MainWindow::aprsClientEnqueueSpot, m_aprsClient, &APRSISClient::enqueueSpot);
connect (this, &MainWindow::aprsClientEnqueueThirdParty, m_aprsClient, &APRSISClient::enqueueThirdParty);
connect (this, &MainWindow::aprsClientSendReports, m_aprsClient, &APRSISClient::sendReports);
connect (this, &MainWindow::aprsClientSetLocalStation, m_aprsClient, &APRSISClient::setLocalStation);
connect (this, &MainWindow::aprsClientSetPaused, m_aprsClient, &APRSISClient::setPaused);
connect (this, &MainWindow::aprsClientSetServer, m_aprsClient, &APRSISClient::setServer);
connect (&m_networkThread, &QThread::finished, m_aprsClient, &QObject::deleteLater);
// hook up sound output stream slots & signals and disposal
connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat);
connect (m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
@ -814,6 +826,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
displayDialFrequency();
readSettings(); //Restore user's setup params
m_networkThread.start(m_networkThreadPriority);
m_audioThread.start (m_audioThreadPriority);
m_notificationAudioThread.start(m_notificationAudioThreadPriority);
m_decoder.start(m_decoderThreadPriority);
@ -2170,6 +2183,9 @@ MainWindow::~MainWindow()
fftwf_export_wisdom_to_filename(cfname);
m_networkThread.quit();
m_networkThread.wait();
m_audioThread.quit ();
m_audioThread.wait ();
@ -2454,6 +2470,7 @@ void MainWindow::readSettings()
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8);
m_notificationAudioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/NotificationThreadPriority", QThread::LowPriority).toInt () % 8);
m_decoderThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/DecoderThreadPriority", QThread::HighPriority).toInt () % 8);
m_networkThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Network/NetworkThreadPriority", QThread::LowPriority).toInt () % 8);
m_settings->endGroup ();
if(m_config.reset_activity()){
@ -3156,11 +3173,11 @@ void MainWindow::prepareSpotting(){
spotSetLocal();
pskSetLocal();
aprsSetLocal();
m_aprsClient->setServer(m_config.aprs_server_name(), m_config.aprs_server_port());
m_aprsClient->setPaused(false);
emit aprsClientSetServer(m_config.aprs_server_name(), m_config.aprs_server_port());
emit aprsClientSetPaused(false);
ui->spotButton->setChecked(true);
} else {
m_aprsClient->setPaused(true);
emit aprsClientSetPaused(true);
ui->spotButton->setChecked(false);
}
}
@ -5232,6 +5249,7 @@ void MainWindow::spotCmd(CommandDetail cmd){
// KN4CRD: @APRSIS CMD :EMAIL-2 :email@domain.com booya{1
void MainWindow::spotAprsCmd(CommandDetail cmd){
if(!m_config.spot_to_reporting_networks()) return;
if(!m_config.spot_to_aprs()) return;
if(cmd.cmd != " CMD") return;
@ -5240,11 +5258,14 @@ void MainWindow::spotAprsCmd(CommandDetail cmd){
auto by_call = Radio::base_callsign(m_config.my_callsign());
auto from_call = Radio::base_callsign(cmd.from);
m_aprsClient->enqueueThirdParty(by_call, from_call, cmd.text);
// we use a queued signal here so we can process these spots in a network thread
// to prevent blocking the gui/decoder while waiting on TCP
emit aprsClientEnqueueThirdParty(by_call, from_call, cmd.text);
}
void MainWindow::spotAprsGrid(int offset, int snr, QString callsign, QString grid){
if(!m_config.spot_to_reporting_networks()) return;
if(!m_config.spot_to_aprs()) return;
if(grid.length() < 4) return;
Frequency frequency = m_freqNominal + offset;
@ -5257,7 +5278,9 @@ void MainWindow::spotAprsGrid(int offset, int snr, QString callsign, QString gri
auto by_call = Radio::base_callsign(m_config.my_callsign());
auto from_call = Radio::base_callsign(callsign);
m_aprsClient->enqueueSpot(by_call, from_call, grid, comment);
// we use a queued signal here so we can process these spots in a network thread
// to prevent blocking the gui/decoder while waiting on TCP
emit aprsClientEnqueueSpot(by_call, from_call, grid, comment);
}
void MainWindow::pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid){
@ -7887,7 +7910,7 @@ void MainWindow::band_changed (Frequency f)
m_bandEdited = false;
psk_Reporter->sendReport(); // Upload any queued spots before changing band
m_aprsClient->sendReports();
emit aprsClientSendReports(); // Upload any queued spots before changing band
if (!m_transmitting) monitor (true);
if ("FreqCal" == m_mode)
@ -9731,7 +9754,7 @@ void MainWindow::pskSetLocal ()
void MainWindow::aprsSetLocal ()
{
m_aprsClient->setLocalStation("APJ8CL", QString::number(APRSISClient::hashCallsign("APJ8CL")));
emit aprsClientSetLocalStation("APJ8CL", QString::number(APRSISClient::hashCallsign("APJ8CL")));
}
void MainWindow::transmitDisplay (bool transmitting)

View File

@ -7,6 +7,8 @@
#include <QtGui>
#endif
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QTimer>
#include <QDateTime>
#include <QList>
@ -434,6 +436,13 @@ private slots:
void refreshTextDisplay();
private:
Q_SIGNAL void aprsClientEnqueueSpot(QString by_call, QString from_call, QString grid, QString comment);
Q_SIGNAL void aprsClientEnqueueThirdParty(QString by_call, QString from_call, QString text);
Q_SIGNAL void aprsClientSetServer(QString host, quint16 port);
Q_SIGNAL void aprsClientSetPaused(bool paused);
Q_SIGNAL void aprsClientSetLocalStation(QString mycall, QString passcode);
Q_SIGNAL void aprsClientSendReports();
Q_SIGNAL void decodedLineReady(QByteArray t);
Q_SIGNAL void playNotification(const QString &name);
Q_SIGNAL void initializeNotificationAudioOutputStream(const QAudioDeviceInfo &, unsigned, unsigned) const;
@ -505,6 +514,8 @@ private:
SoundOutput * m_soundOutput;
NotificationAudio * m_notification;
QMutex m_networkThreadMutex;
QThread m_networkThread;
QThread m_audioThread;
QThread m_notificationAudioThread;
Decoder m_decoder;
@ -904,6 +915,7 @@ private:
QThread::Priority m_audioThreadPriority;
QThread::Priority m_notificationAudioThreadPriority;
QThread::Priority m_decoderThreadPriority;
QThread::Priority m_networkThreadPriority;
bool m_bandEdited;
bool m_splitMode;
bool m_monitoring;