• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • plugins
  • render
  • aprs
AprsGatherer.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2010 Wes Hardaker <hardaker@users.sourceforge.net>
9 //
10 
11 #include "AprsGatherer.h"
12 
13 #include <QPixmap>
14 
15 #include "MarbleDirs.h"
16 #include "MarbleDebug.h"
17 
18 using namespace Marble;
19 
20 AprsGatherer::AprsGatherer( AprsSource *from,
21  QMap<QString, AprsObject *> *objects,
22  QMutex *mutex,
23  QString *filter )
24  : m_source( from ),
25  m_socket( 0 ),
26  m_filter( filter ),
27  m_running( true ),
28  m_dumpOutput( false ),
29  m_seenFrom( GeoAprsCoordinates::FromNowhere ),
30  m_sourceName( ),
31  m_mutex( mutex ),
32  m_objects( objects )
33 {
34  m_sourceName = from->sourceName();
35  initMicETables();
36 }
37 
38 AprsGatherer::AprsGatherer( QIODevice *from,
39  QMap<QString, AprsObject *> *objects,
40  QMutex *mutex,
41  QString *filter )
42  : m_source( 0 ),
43  m_socket( from ),
44  m_filter( filter ),
45  m_running( true ),
46  m_dumpOutput( false ),
47  m_seenFrom( GeoAprsCoordinates::FromNowhere ),
48  m_sourceName( "unknown" ),
49  m_mutex( mutex ),
50  m_objects( objects )
51 {
52  initMicETables();
53 }
54 
55 void
56 AprsGatherer::run()
57 {
58  char buf[4096];
59  qint64 linelength;
60  // one particular APRS packet sender can add data after the : ( sigh )
61  QRegExp matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^:]*):([!=@\\/])([0-9][0-9][0-9][0-9][0-9][0-9]|)([hz\\/]|)([0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([NS])(.)([0-9][0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([EW])(.)" );
62 
63  // mic-e formatted
64  // 1: src
65  // 2: dst
66  // 3: routes
67  // 4: longitude x 3
68  // 5: speed and course x3
69  // 6: symbol and symbol ID
70  // 7: status text
71  QRegExp mic_e_matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^,:]*),*([^:]*):['`](...)(...)(..)(.*)" );
72 
73  // If a source can directly receive a signal (as opposed to
74  // through a relay like the internet) will return true. This
75  // prevents accidentially coloring signals heard over some sources
76  // as heard directly where it's never possible (such as over the
77  // internet).
78  bool canDoDirect = m_source->canDoDirect();
79 
80  while( m_running ) {
81 
82  if ( m_socket && !m_socket->isOpen() ) {
83  // connection closed; attempt to reopen
84  mDebug() << "aprs: socket closed; attempting to reopen";
85  delete m_socket;
86  m_socket = 0;
87  }
88 
89 
90  if ( !m_socket && m_source )
91  m_socket = m_source->openSocket();
92 
93  if ( !m_socket ) {
94  mDebug() << "aprs: failed to open socket from "
95  << m_sourceName.toLocal8Bit().data();
96  sleep( 5 );
97  continue;
98  }
99 
100  // wait for data to read in
101  if ( m_socket->bytesAvailable() <= 0 )
102  // wait no longer than 1s
103  if ( ! m_socket->waitForReadyRead( 1000 ) )
104  continue; // continue to loop again on "not ready"
105 
106  // Read the line to parse
107  linelength = m_socket->readLine( buf, sizeof( buf ) );
108 
109  // if we got 0 or less bytes this is probably an odd case; ask
110  // the source what to do.
111  m_source->checkReadReturn( linelength, &m_socket, this );
112 
113  if ( linelength <= 0 ) {
114  // don't go into an infinite untimed loop of failed sockets
115  sleep( 2 );
116  continue;
117  }
118 
119  if ( m_socket && m_filter != NULL ) {
120  QMutexLocker locker( m_mutex );
121  if ( m_filter->length() > 0 ) {
122  m_socket->write( m_filter->toLocal8Bit().data(),
123  m_filter->length() );
124  }
125  }
126 
127  // Parse the results
128  QString line( buf );
129 
130  // Dump it out if we wanted it dumped
131  if ( m_dumpOutput )
132  mDebug() << "aprs: " << m_sourceName.toLocal8Bit().data()
133  << ": " << line;
134 
135  if ( matcher.indexIn( line ) != -1 ) {
136  QString callSign = matcher.cap( 1 );
137  qreal latitude = matcher.cap( 6 ).toFloat() +
138  ( matcher.cap( 7 ).toFloat()/60 );
139  if ( matcher.cap( 8 ) == "S" )
140  latitude = - latitude;
141 
142  qreal longitude = matcher.cap( 10 ).toFloat() +
143  ( matcher.cap( 11 ).toFloat()/60 );
144  if ( matcher.cap( 12 ) == "W" )
145  longitude = - longitude;
146 
147  addObject( callSign, latitude, longitude, canDoDirect,
148  QString( matcher.cap( 2 ) ),
149  QChar( matcher.cap( 9 )[0] ),
150  QChar( matcher.cap( 13 )[0] ) );
151  }
152  else if ( mic_e_matcher.indexIn( line ) != -1 ) {
153  // MIC-E formatted compressed packet
154  QString myCall = mic_e_matcher.cap( 1 );
155  QString dstCall = mic_e_matcher.cap( 2 );
156 
157  qreal latitude =
158  // hours
159  m_dstCallDigits[dstCall[0]] * 10 +
160  m_dstCallDigits[dstCall[1]] +
161 
162  // minutes
163  ( qreal( m_dstCallDigits[dstCall[2]] * 10 +
164  m_dstCallDigits[dstCall[3]] ) +
165  qreal( m_dstCallDigits[dstCall[4]] ) / 10.0 +
166  qreal( m_dstCallDigits[dstCall[5]] ) / 100 ) / 60.0;
167 
168  if ( m_dstCallSouthEast[dstCall[4]] )
169  latitude = - latitude;
170 
171  qreal longitude =
172  calculateLongitude( QString ( mic_e_matcher.cap( 4 ) ),
173  m_dstCallLongitudeOffset[dstCall[5]],
174  m_dstCallSouthEast[dstCall[6]] );
175 
176 // mDebug() << " MIC-E: " << line.toLocal8Bit().data();
177 // mDebug() << " lat: " << latitude;
178 // mDebug() << " lon: " << longitude;
179 
180  addObject( myCall, latitude, longitude, canDoDirect,
181  QString( mic_e_matcher.cap( 3 ) ),
182  QChar( mic_e_matcher.cap( 6 )[1] ),
183  QChar( mic_e_matcher.cap( 6 )[0] ) );
184  }
185  else {
186  mDebug() << "aprs: UNPARSED: " << line;
187  }
188 
189  // If the filter should be changed, send it out the socket
190  if ( m_filter != NULL ) {
191  QMutexLocker locker( m_mutex );
192  if ( m_filter->length() > 0 ) {
193  m_socket->write( m_filter->toLocal8Bit().data(),
194  m_filter->length() );
195  }
196  }
197  }
198 }
199 
200 void
201 AprsGatherer::shutDown()
202 {
203  m_running = false;
204 }
205 
206 void
207 AprsGatherer::addObject( const QString &callSign,
208  qreal latitude, qreal longitude, bool canDoDirect,
209  const QString &routePath,
210  const QChar &symbolTable,
211  const QChar &symbolCode )
212 {
213  QMutexLocker locker( m_mutex );
214 
215  GeoAprsCoordinates location( longitude, latitude, m_seenFrom );
216  if ( canDoDirect ) {
217  if ( !routePath.contains( QChar( '*' ) ) ) {
218  location.addSeenFrom( GeoAprsCoordinates::Directly );
219  }
220  }
221 
222  if ( m_objects->contains( callSign ) ) {
223  // we already have one for this callSign; just add the new
224  // history item.
225  ( *m_objects )[callSign]->setLocation( location );
226  }
227  else {
228  AprsObject *foundObject = new AprsObject( location, callSign );
229  foundObject->setPixmapId( m_pixmaps[QPair<QChar, QChar>( symbolTable,symbolCode )] );
230  ( *m_objects )[callSign] = foundObject;
231  mDebug() << "aprs: new: " << callSign.toLocal8Bit().data();
232  }
233 }
234 
235 void AprsGatherer::initMicETables()
236 {
237 #include "AprsGatherer_mic_e.h"
238 }
239 
240 qreal AprsGatherer::calculateLongitude( const QString &threeBytes, int offset,
241  bool isEast )
242 {
243  // otherwise known as "fun with funky encoding"
244  qreal hours = threeBytes[0].toLatin1() - 28 + offset;
245  if ( 180 <= hours && hours <= 189 )
246  hours -= 80;
247  if ( 190 <= hours && hours <= 199 )
248  hours -= 190;
249 
250  hours +=
251  ( qreal( (threeBytes[1].toLatin1() - 28 ) % 60 ) +
252  ( qreal( threeBytes[2].toLatin1() - 28 ) ) / 100 ) / 60.0;
253 
254  if ( ! isEast )
255  hours = -hours;
256  return hours;
257 }
258 
259 void
260 AprsGatherer::setDumpOutput( bool to )
261 {
262  m_dumpOutput = to;
263 }
264 
265 bool
266 AprsGatherer::dumpOutput() const
267 {
268  return m_dumpOutput;
269 }
270 
271 void
272 AprsGatherer::setSeenFrom( GeoAprsCoordinates::SeenFrom to )
273 {
274  m_seenFrom = to;
275 }
276 
277 GeoAprsCoordinates::SeenFrom
278 AprsGatherer::seenFrom()
279 {
280  return m_seenFrom;
281 }
282 
283 // gets around parent QThread protected sleep as our objects need a sleep
284 void
285 AprsGatherer::sleepFor(int seconds)
286 {
287  sleep(seconds);
288 }
289 
290 #include "AprsGatherer.moc"
QIODevice
QMutex
QRegExp::cap
QString cap(int nth) const
QThread::sleep
void sleep(unsigned long secs)
QChar
Marble::AprsSource::canDoDirect
virtual bool canDoDirect() const =0
Marble::GeoAprsCoordinates::Directly
Definition: GeoAprsCoordinates.h:28
Marble::AprsGatherer::setSeenFrom
void setSeenFrom(GeoAprsCoordinates::SeenFrom seenFrom)
Definition: AprsGatherer.cpp:272
QMap
MarbleDebug.h
Marble::AprsGatherer::seenFrom
GeoAprsCoordinates::SeenFrom seenFrom()
Definition: AprsGatherer.cpp:278
AprsGatherer.h
Marble::AprsObject
Definition: AprsObject.h:23
Marble::AprsSource::openSocket
virtual QIODevice * openSocket()=0
QRegExp::indexIn
int indexIn(const QString &str, int offset, CaretMode caretMode) const
Marble::GeoAprsCoordinates::SeenFrom
SeenFrom
Definition: GeoAprsCoordinates.h:23
QRegExp
Marble::GeoAprsCoordinates::addSeenFrom
void addSeenFrom(int where)
Definition: GeoAprsCoordinates.cpp:28
Marble::AprsGatherer::shutDown
void shutDown()
Definition: AprsGatherer.cpp:201
Marble::AprsGatherer::addObject
void addObject(const QString &callSign, qreal latitude, qreal longitude, bool canDoDirect, const QString &routePath, const QChar &symbolTable, const QChar &symbolCode)
Definition: AprsGatherer.cpp:207
Marble::AprsObject::setPixmapId
void setPixmapId(QString &pixmap)
Definition: AprsObject.cpp:62
MarbleDirs.h
Marble::AprsSource
Definition: AprsSource.h:20
QIODevice::waitForReadyRead
virtual bool waitForReadyRead(int msecs)
QIODevice::isOpen
bool isOpen() const
Marble::AprsSource::sourceName
virtual QString sourceName() const =0
Marble::AprsGatherer::run
void run()
Definition: AprsGatherer.cpp:56
Marble::AprsGatherer::dumpOutput
bool dumpOutput() const
Definition: AprsGatherer.cpp:266
QString
QIODevice::bytesAvailable
virtual qint64 bytesAvailable() const
QPair
Marble::AprsGatherer::AprsGatherer
AprsGatherer(AprsSource *from, QMap< QString, AprsObject * > *objects, QMutex *mutex, QString *filter)
Definition: AprsGatherer.cpp:20
QString::toLocal8Bit
QByteArray toLocal8Bit() const
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
Marble::AprsSource::checkReadReturn
virtual void checkReadReturn(int length, QIODevice **socket, AprsGatherer *gatherer)=0
QString::toLatin1
QByteArray toLatin1() const
Marble::AprsGatherer::sleepFor
static void sleepFor(int seconds)
Definition: AprsGatherer.cpp:285
Marble::GeoAprsCoordinates
Definition: GeoAprsCoordinates.h:19
QMutexLocker
QString::toFloat
float toFloat(bool *ok) const
Marble::AprsGatherer::setDumpOutput
void setDumpOutput(bool to)
Definition: AprsGatherer.cpp:260
QString::length
int length() const
QByteArray::data
char * data()
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
AprsGatherer_mic_e.h
QIODevice::readLine
qint64 readLine(char *data, qint64 maxSize)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:38 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal