File indexing completed on 2024-04-28 03:50:13

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2010 Wes Hardaker <hardaker@users.sourceforge.net>
0004 //
0005 
0006 #include "AprsPlugin.h"
0007 
0008 #include "MarbleGlobal.h"
0009 #include "MarbleDebug.h"
0010 
0011 #include <QColor>
0012 #include <QAction>
0013 #include <QMutexLocker>
0014 #include <QTcpSocket>
0015 
0016 #include "MarbleDirs.h"
0017 #include "MarbleWidget.h"
0018 #include "GeoPainter.h"
0019 #include "GeoDataCoordinates.h"
0020 #include "MarbleModel.h"
0021 #include "ViewportParams.h"
0022 #include "AprsTCPIP.h"
0023 #include "AprsFile.h"
0024 
0025 #include <aprsconfig.h>
0026 
0027 #if HAVE_QTSERIALPORT
0028 #include "AprsTTY.h"
0029 #endif
0030 
0031 using namespace Marble;
0032 /* TRANSLATOR Marble::AprsPlugin */
0033 
0034 AprsPlugin::AprsPlugin( const MarbleModel *marbleModel )
0035     : RenderPlugin( marbleModel ),
0036       m_mutex( new QMutex ),
0037       m_initialized( false ),
0038       m_tcpipGatherer( nullptr ),
0039       m_ttyGatherer( nullptr ),
0040       m_fileGatherer( nullptr ),
0041       m_action( nullptr ),
0042       m_useInternet( true ),
0043       m_useTty( false ),
0044       m_useFile( false ),
0045       m_aprsHost( "rotate.aprs.net" ),
0046       m_aprsPort( 10253 ),
0047       m_tncTty( "/dev/ttyUSB0" ),
0048       m_aprsFile(),
0049       m_dumpTcpIp( false ),
0050       m_dumpTty( false ),
0051       m_dumpFile( false ),
0052       m_fadeTime( 10 ),
0053       m_hideTime( 45 ),
0054       m_configDialog( nullptr ),
0055       ui_configWidget( nullptr )
0056 {
0057     setEnabled( true );
0058     setVisible( false );
0059     
0060     setSettings( QHash<QString,QVariant>() );
0061 
0062     connect( this, SIGNAL(visibilityChanged(bool,QString)),
0063              this, SLOT(updateVisibility(bool)) );
0064 
0065     m_action = new QAction( this );
0066     connect( m_action,    SIGNAL(toggled(bool)),
0067          this,        SLOT(setVisible(bool)) );
0068 
0069 }
0070 
0071 AprsPlugin::~AprsPlugin()
0072 {
0073     stopGatherers();
0074 
0075     delete m_configDialog;
0076     delete ui_configWidget;
0077 
0078     QMap<QString, AprsObject *>::Iterator obj;
0079     QMap<QString, AprsObject *>::Iterator end = m_objects.end();
0080 
0081     for( obj = m_objects.begin(); obj != end; ++obj ) {
0082         delete *obj;
0083     }
0084 
0085     m_objects.clear();
0086 
0087     delete m_mutex;
0088 }
0089 
0090 void AprsPlugin::updateVisibility( bool visible )
0091 {
0092     if ( visible )
0093         restartGatherers();
0094     else
0095         stopGatherers();
0096 }
0097 
0098 RenderPlugin::RenderType AprsPlugin::renderType() const
0099 {
0100     return OnlineRenderType;
0101 }
0102 
0103 QStringList AprsPlugin::backendTypes() const
0104 {
0105     return QStringList(QStringLiteral("aprs"));
0106 }
0107 
0108 QString AprsPlugin::renderPolicy() const
0109 {
0110     return QStringLiteral("ALWAYS");
0111 }
0112 
0113 QStringList AprsPlugin::renderPosition() const
0114 {
0115     return QStringList(QStringLiteral("HOVERS_ABOVE_SURFACE"));
0116 }
0117 
0118 QString AprsPlugin::name() const
0119 {
0120     return tr( "Amateur Radio Aprs Plugin" );
0121 }
0122 
0123 QString AprsPlugin::guiString() const
0124 {
0125     return tr( "Amateur Radio &Aprs Plugin" );
0126 }
0127 
0128 QString AprsPlugin::nameId() const
0129 {
0130     return QStringLiteral("aprs-plugin");
0131 }
0132 
0133 QString AprsPlugin::version() const
0134 {
0135     return QStringLiteral("1.0");
0136 }
0137 
0138 QString AprsPlugin::description() const
0139 {
0140     return tr( "This plugin displays APRS data gleaned from the Internet.  APRS is an Amateur Radio protocol for broadcasting location and other information." );
0141 }
0142 
0143 QString AprsPlugin::copyrightYears() const
0144 {
0145     return QStringLiteral("2009, 2010");
0146 }
0147 
0148 QVector<PluginAuthor> AprsPlugin::pluginAuthors() const
0149 {
0150     return QVector<PluginAuthor>()
0151             << PluginAuthor(QStringLiteral("Wes Hardaker"), QStringLiteral("hardaker@users.sourceforge.net"));
0152 }
0153 
0154 QIcon AprsPlugin::icon () const
0155 {
0156     return QIcon(QStringLiteral(":/icons/aprs.png"));
0157 }
0158 
0159 void AprsPlugin::stopGatherers()
0160 {
0161 
0162     // tell them all to stop
0163     if ( m_tcpipGatherer )
0164         m_tcpipGatherer->shutDown();
0165 
0166 #if HAVE_QTSERIALPORT
0167     if ( m_ttyGatherer )
0168         m_ttyGatherer->shutDown();
0169 #endif
0170     
0171     if ( m_fileGatherer )
0172         m_fileGatherer->shutDown();
0173     
0174     // now wait for them for at least 2 seconds (it shouldn't take that long)
0175     if ( m_tcpipGatherer )
0176         if ( m_tcpipGatherer->wait(2000) )
0177             delete m_tcpipGatherer;
0178 
0179 #if HAVE_QTSERIALPORT
0180     if ( m_ttyGatherer )
0181         if ( m_ttyGatherer->wait(2000) )
0182             delete m_ttyGatherer;
0183 #endif
0184     
0185     if ( m_fileGatherer )
0186         if ( m_fileGatherer->wait(2000) )
0187             delete m_fileGatherer;
0188 
0189     m_tcpipGatherer = nullptr;
0190     m_ttyGatherer = nullptr;
0191     m_fileGatherer = nullptr;
0192 }
0193 
0194 void AprsPlugin::restartGatherers()
0195 {
0196     stopGatherers();
0197 
0198     if ( m_useInternet ) {
0199         m_tcpipGatherer =
0200             new AprsGatherer( new AprsTCPIP( m_aprsHost, m_aprsPort ),
0201                               &m_objects, m_mutex, &m_filter);
0202         m_tcpipGatherer->setSeenFrom( GeoAprsCoordinates::FromTCPIP );
0203         m_tcpipGatherer->setDumpOutput( m_dumpTcpIp );
0204 
0205         m_tcpipGatherer->start();
0206         mDebug() << "started TCPIP gatherer";
0207     }
0208 
0209 #if HAVE_QTSERIALPORT
0210     if ( m_useTty ) {
0211         m_ttyGatherer =
0212             new AprsGatherer( new AprsTTY( m_tncTty ),
0213                               &m_objects, m_mutex, nullptr);
0214 
0215         m_ttyGatherer->setSeenFrom( GeoAprsCoordinates::FromTTY );
0216         m_ttyGatherer->setDumpOutput( m_dumpTty );
0217 
0218         m_ttyGatherer->start();
0219         mDebug() << "started TTY gatherer";
0220     }
0221 #endif
0222 
0223     
0224     if ( m_useFile ) {
0225         m_fileGatherer = 
0226             new AprsGatherer( new AprsFile( m_aprsFile ),
0227                               &m_objects, m_mutex, nullptr);
0228 
0229         m_fileGatherer->setSeenFrom( GeoAprsCoordinates::FromFile );
0230         m_fileGatherer->setDumpOutput( m_dumpFile );
0231 
0232         m_fileGatherer->start();
0233         mDebug() << "started File gatherer";
0234     }
0235 }
0236 
0237 
0238 void AprsPlugin::initialize ()
0239 {
0240     m_initialized = true;
0241     mDebug() << "APRS initialized";
0242 
0243     restartGatherers();
0244 }
0245 
0246 QDialog *AprsPlugin::configDialog()
0247 {
0248     if ( !m_configDialog ) {
0249         // Initializing configuration dialog
0250         m_configDialog = new QDialog();
0251         ui_configWidget = new Ui::AprsConfigWidget;
0252         ui_configWidget->setupUi( m_configDialog );
0253         readSettings();
0254         connect( ui_configWidget->m_buttonBox, SIGNAL(accepted()),
0255                  SLOT(writeSettings()) );
0256         connect( ui_configWidget->m_buttonBox, SIGNAL(rejected()),
0257                  SLOT(readSettings()) );
0258         //       QPushButton *applyButton =
0259 //             ui_configWidget->m_buttonBox->button( QDialogButtonBox::Apply );
0260 //         connect( applyButton, SIGNAL(clicked()),
0261 //                  this,        SLOT(writeSettings()) );
0262     }
0263     return m_configDialog;
0264 }
0265 
0266 void AprsPlugin::readSettings()
0267 {
0268     if ( !m_configDialog ) {
0269         return;
0270     }
0271 
0272 #ifndef HAVE_QTSERIALPORT
0273     ui_configWidget->tabWidget->setTabEnabled( ui_configWidget->tabWidget->indexOf(
0274                                                    ui_configWidget->Device ), false );
0275 #endif
0276 
0277     // Connect to the net?
0278     if ( m_useInternet )
0279         ui_configWidget->m_internetBox->setCheckState( Qt::Checked );
0280     else
0281         ui_configWidget->m_internetBox->setCheckState( Qt::Unchecked );
0282 
0283     // Connection Information
0284     ui_configWidget->m_serverName->setText( m_aprsHost );
0285     ui_configWidget->m_serverPort->setText( QString::number( m_aprsPort ) );
0286 
0287     // Read from a TTY serial port?
0288     if ( m_useTty )
0289         ui_configWidget->m_serialBox->setCheckState( Qt::Checked );
0290     else
0291         ui_configWidget->m_serialBox->setCheckState( Qt::Unchecked );
0292 
0293     // Serial port to use
0294     ui_configWidget->m_ttyName->setText( m_tncTty );
0295 
0296     // Read from a File?
0297     if ( m_useFile )
0298         ui_configWidget->m_useFile->setCheckState( Qt::Checked );
0299     else
0300         ui_configWidget->m_useFile->setCheckState( Qt::Unchecked );
0301 
0302     // Serial port to use
0303     ui_configWidget->m_fileName->setText( m_aprsFile );
0304 
0305     // Dumping settings
0306     if ( m_dumpTcpIp )
0307         ui_configWidget->m_tcpipdump->setCheckState( Qt::Checked );
0308     else
0309         ui_configWidget->m_tcpipdump->setCheckState( Qt::Unchecked );
0310 
0311     if ( m_dumpTty )
0312         ui_configWidget->m_ttydump->setCheckState( Qt::Checked );
0313     else
0314         ui_configWidget->m_ttydump->setCheckState( Qt::Unchecked );
0315 
0316     if ( m_dumpFile )
0317         ui_configWidget->m_filedump->setCheckState( Qt::Checked );
0318     else
0319         ui_configWidget->m_filedump->setCheckState( Qt::Unchecked );
0320 
0321     // display settings
0322     ui_configWidget->m_fadetime->setText( QString::number( m_fadeTime ) );
0323     ui_configWidget->m_hidetime->setText( QString::number( m_hideTime ) );
0324 }
0325 
0326 
0327 void AprsPlugin::writeSettings()
0328 {
0329     m_useInternet = ui_configWidget->m_internetBox->checkState() == Qt::Checked;
0330     m_useTty = ui_configWidget->m_serialBox->checkState() == Qt::Checked;
0331     m_useFile = ui_configWidget->m_useFile->checkState() == Qt::Checked;
0332 
0333     m_aprsHost = ui_configWidget->m_serverName->text();
0334     m_aprsPort = ui_configWidget->m_serverPort->text().toInt();
0335     m_tncTty = ui_configWidget->m_ttyName->text();
0336 
0337     m_dumpTcpIp = ui_configWidget->m_tcpipdump->checkState() == Qt::Checked;
0338     m_dumpTty = ui_configWidget->m_ttydump->checkState() == Qt::Checked;
0339     m_dumpFile = ui_configWidget->m_filedump->checkState() == Qt::Checked;
0340 
0341     m_fadeTime = ui_configWidget->m_fadetime->text().toInt();
0342     m_hideTime = ui_configWidget->m_hidetime->text().toInt();
0343 
0344     restartGatherers();
0345     emit settingsChanged( nameId() );
0346 }
0347 
0348 QHash<QString,QVariant> AprsPlugin::settings() const
0349 {
0350     QHash<QString, QVariant> result = RenderPlugin::settings();
0351 
0352     result.insert(QStringLiteral("useInternet"), m_useInternet);
0353     result.insert(QStringLiteral("useTTY"), m_useTty);
0354     result.insert(QStringLiteral("useFile"), m_useFile);
0355     result.insert(QStringLiteral("APRSHost"), m_aprsHost);
0356     result.insert(QStringLiteral("APRSPort"), m_aprsPort);
0357     result.insert(QStringLiteral("TNCTTY"), m_tncTty);
0358     result.insert(QStringLiteral("FileName"), m_aprsFile);
0359     result.insert(QStringLiteral("TCPIPDump"), m_dumpTcpIp);
0360     result.insert(QStringLiteral("TTYDump"), m_dumpTty);
0361     result.insert(QStringLiteral("FileDump"), m_dumpFile);
0362     result.insert(QStringLiteral("fadeTime"), m_fadeTime);
0363     result.insert(QStringLiteral("hideTime"), m_hideTime);
0364 
0365     return result;
0366 }
0367 
0368 void AprsPlugin::setSettings( const QHash<QString,QVariant> &settings )
0369 {
0370     RenderPlugin::setSettings( settings );
0371 
0372     m_useInternet =  settings.value(QStringLiteral("useInternet"), true).toBool();
0373     m_useTty = settings.value(QStringLiteral("useTTY"), false).toBool();
0374     m_useFile = settings.value(QStringLiteral("useFile"), false).toBool();
0375 
0376     m_aprsHost = settings.value(QStringLiteral("APRSHost"), QStringLiteral("rotate.aprs.net")).toString();
0377     m_aprsPort = settings.value(QStringLiteral("APRSPort"), 10253).toInt();
0378     m_tncTty = settings.value(QStringLiteral("TNCTTY"), QStringLiteral("/dev/ttyUSB0")).toString();
0379     m_aprsFile = settings.value(QStringLiteral("FileName"), QString()).toString();
0380 
0381     m_dumpTcpIp = settings.value(QStringLiteral("TCPIPDump"), false).toBool();
0382     m_dumpTty = settings.value(QStringLiteral("TTYDump"), false).toBool();
0383     m_dumpFile = settings.value(QStringLiteral("FileDump"), false).toBool();
0384 
0385     m_fadeTime = settings.value(QStringLiteral("fadeTime"), 10).toInt();
0386     m_hideTime = settings.value(QStringLiteral("hideTime"), 45).toInt();
0387 
0388     readSettings();
0389     emit settingsChanged( nameId() );
0390 }
0391 
0392 bool AprsPlugin::isInitialized () const
0393 {
0394     return m_initialized;
0395 }
0396 
0397 bool AprsPlugin::render( GeoPainter *painter, ViewportParams *viewport, const QString& renderPos, GeoSceneLayer * layer )
0398 {
0399     Q_UNUSED( renderPos )
0400     Q_UNUSED( layer )
0401 
0402     int fadetime = m_fadeTime * 60000;
0403     int hidetime = m_hideTime * 60000;
0404 
0405     painter->save();
0406 
0407     if ( !( viewport->viewLatLonAltBox() == m_lastBox ) ) {
0408         m_lastBox = viewport->viewLatLonAltBox();
0409         QString towrite = QLatin1String("#filter a/") +
0410             QString::number(m_lastBox.north(GeoDataCoordinates::Degree)) + QLatin1Char('/') +
0411             QString::number(m_lastBox.west(GeoDataCoordinates::Degree))  + QLatin1Char('/') +
0412             QString::number(m_lastBox.south(GeoDataCoordinates::Degree)) + QLatin1Char('/') +
0413             QString::number(m_lastBox.east(GeoDataCoordinates::Degree))  + QLatin1Char('\n');
0414         mDebug() << "upating filter: " << towrite.toLocal8Bit().data();
0415 
0416         QMutexLocker locker( m_mutex );
0417         m_filter = towrite;
0418     }
0419     
0420 
0421     QMutexLocker locker( m_mutex );
0422     QMap<QString, AprsObject *>::ConstIterator obj;
0423     for( obj = m_objects.constBegin(); obj != m_objects.constEnd(); ++obj ) {
0424         ( *obj )->render( painter, viewport, fadetime, hidetime );
0425     }
0426 
0427     painter->restore();
0428 
0429     return true;
0430 }
0431 
0432 QAction* AprsPlugin::action() const
0433 {
0434     m_action->setCheckable( true );
0435     m_action->setChecked( visible() );
0436     m_action->setIcon( icon() );
0437     m_action->setText( guiString() );
0438     m_action->setToolTip( description() );
0439     return m_action;
0440 }
0441 
0442 #include "moc_AprsPlugin.cpp"