summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbin Olsson <albin.olsson@cybercom.com>2013-08-30 12:56:31 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-03 13:18:53 +0200
commit5611ad387a9ff1f6383773d6108f257a1338e921 (patch)
treec8439056199bebc94f535c8293c072d048c29132
parentd26ab7e17cebbdf0ad3fe7ea5208dec8ac8dcef8 (diff)
Implement socket NMEA source.
nmeaSource property of PositionSource is limited to log files. This change adds possibility of using a TCP socket instead. This is a lot more useful when testing because it can be used with a simulator. Change-Id: Ie6fb2b5344aae2702a8cf53d0146780d6ea1e0f9 Reviewed-by: Albin Olsson <albin.olsson@cybercom.com> Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
-rw-r--r--src/imports/positioning/qdeclarativepositionsource.cpp176
-rw-r--r--src/imports/positioning/qdeclarativepositionsource_p.h8
-rw-r--r--src/positioning/doc/src/qml-position.qdoc14
3 files changed, 149 insertions, 49 deletions
diff --git a/src/imports/positioning/qdeclarativepositionsource.cpp b/src/imports/positioning/qdeclarativepositionsource.cpp
index 97ad1bbc..00775010 100644
--- a/src/imports/positioning/qdeclarativepositionsource.cpp
+++ b/src/imports/positioning/qdeclarativepositionsource.cpp
@@ -47,6 +47,7 @@
#include <QtQml/qqml.h>
#include <qnmeapositioninfosource.h>
#include <QFile>
+#include <QTcpSocket>
#include <QTimer>
QT_BEGIN_NAMESPACE
@@ -116,13 +117,15 @@ QT_BEGIN_NAMESPACE
QDeclarativePositionSource::QDeclarativePositionSource()
: m_positionSource(0), m_preferredPositioningMethods(NoPositioningMethod), m_nmeaFile(0),
- m_active(false), m_singleUpdate(false), m_updateInterval(0), m_sourceError(UnknownSourceError)
+ m_nmeaSocket(0), m_active(false), m_singleUpdate(false), m_updateInterval(0),
+ m_sourceError(UnknownSourceError)
{
}
QDeclarativePositionSource::~QDeclarativePositionSource()
{
delete m_nmeaFile;
+ delete m_nmeaSocket;
delete m_positionSource;
}
@@ -218,67 +221,145 @@ bool QDeclarativePositionSource::isValid() const
*/
void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource)
{
- // Strip the filename. This is clumsy but the file may be prefixed in several
- // ways: "file:///", "qrc:///", "/", "" in platform dependant manner.
- QString localFileName = nmeaSource.toString();
- if (!QFile::exists(localFileName)) {
- if (localFileName.startsWith("qrc:///")) {
- localFileName.remove(0, 7);
- } else if (localFileName.startsWith("file:///")) {
- localFileName.remove(0, 7);
+ if (nmeaSource.scheme() == QLatin1String("socket")) {
+ if (m_nmeaSocket
+ && nmeaSource.host() == m_nmeaSocket->peerName()
+ && nmeaSource.port() == m_nmeaSocket->peerPort()) {
+ return;
}
- if (!QFile::exists(localFileName) && localFileName.startsWith("/")) {
- localFileName.remove(0,1);
+
+ delete m_nmeaSocket;
+ m_nmeaSocket = new QTcpSocket();
+
+ connect(m_nmeaSocket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)> (&QAbstractSocket::error),
+ this, &QDeclarativePositionSource::socketError);
+ connect(m_nmeaSocket, &QTcpSocket::connected,
+ this, &QDeclarativePositionSource::socketConnected);
+
+ m_nmeaSocket->connectToHost(nmeaSource.host(), nmeaSource.port(), QTcpSocket::ReadOnly);
+ } else {
+ // Strip the filename. This is clumsy but the file may be prefixed in several
+ // ways: "file:///", "qrc:///", "/", "" in platform dependent manner.
+ QString localFileName = nmeaSource.toString();
+ if (!QFile::exists(localFileName)) {
+ if (localFileName.startsWith("qrc:///")) {
+ localFileName.remove(0, 7);
+ } else if (localFileName.startsWith("file:///")) {
+ localFileName.remove(0, 7);
+ }
+ if (!QFile::exists(localFileName) && localFileName.startsWith("/")) {
+ localFileName.remove(0,1);
+ }
+ }
+ if (m_nmeaFileName == localFileName)
+ return;
+ m_nmeaFileName = localFileName;
+
+ PositioningMethods previousPositioningMethods = supportedPositioningMethods();
+
+ // The current position source needs to be deleted
+ // because QNmeaPositionInfoSource can be bound only to a one file.
+ delete m_nmeaSocket;
+ m_nmeaSocket = 0;
+ delete m_positionSource;
+ m_positionSource = 0;
+ // Create the NMEA source based on the given data. QML has automatically set QUrl
+ // type to point to correct path. If the file is not found, check if the file actually
+ // was an embedded resource file.
+ delete m_nmeaFile;
+ m_nmeaFile = new QFile(localFileName);
+ if (!m_nmeaFile->exists()) {
+ localFileName.prepend(":");
+ m_nmeaFile->setFileName(localFileName);
+ }
+ if (m_nmeaFile->exists()) {
+#ifdef QDECLARATIVE_POSITION_DEBUG
+ qDebug() << "QDeclarativePositionSource NMEA File was found: " << localFileName;
+#endif
+ m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode);
+ (qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaFile);
+ connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
+ this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
+ if (m_active && !m_singleUpdate) {
+ // Keep on updating even though source changed
+ QTimer::singleShot(0, this, SLOT(start()));
+ }
+ } else {
+ qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, MISSED_NMEA_FILE) << localFileName;
+#ifdef QDECLARATIVE_POSITION_DEBUG
+ qDebug() << "QDeclarativePositionSource NMEA File was not found: " << localFileName;
+#endif
+ if (m_active) {
+ m_active = false;
+ m_singleUpdate = false;
+ emit activeChanged();
+ }
}
+
+ if (previousPositioningMethods != supportedPositioningMethods())
+ emit supportedPositioningMethodsChanged();
}
- if (m_nmeaFileName == localFileName)
- return;
- m_nmeaFileName = localFileName;
+
m_nmeaSource = nmeaSource;
+ emit nmeaSourceChanged();
+}
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::socketConnected()
+{
+#ifdef QDECLARATIVE_POSITION_DEBUG
+ qDebug() << "Socket connected: " << m_nmeaSocket->peerName();
+#endif
PositioningMethods previousPositioningMethods = supportedPositioningMethods();
// The current position source needs to be deleted
// because QNmeaPositionInfoSource can be bound only to a one file.
- delete m_positionSource;
- m_positionSource = 0;
- // Create the NMEA source based on the given data. QML has automatically set QUrl
- // type to point to correct path. If the file is not found, check if the file actually
- // was an embedded resource file.
delete m_nmeaFile;
- m_nmeaFile = new QFile(localFileName);
- if (!m_nmeaFile->exists()) {
- localFileName.prepend(":");
- m_nmeaFile->setFileName(localFileName);
- }
- if (m_nmeaFile->exists()) {
-#ifdef QDECLARATIVE_POSITION_DEBUG
- qDebug() << "QDeclarativePositionSource NMEA File was found: " << localFileName;
-#endif
- m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode);
- (qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaFile);
- connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
- this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
- if (m_active && !m_singleUpdate) {
- // Keep on updating even though source changed
- QTimer::singleShot(0, this, SLOT(start()));
- }
- } else {
- qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, MISSED_NMEA_FILE) << localFileName;
-#ifdef QDECLARATIVE_POSITION_DEBUG
- qDebug() << "QDeclarativePositionSource NMEA File was not found: " << localFileName;
-#endif
- if (m_active) {
- m_active = false;
- m_singleUpdate = false;
- emit activeChanged();
- }
+ m_nmeaFile = 0;
+ delete m_positionSource;
+
+ m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode);
+ (qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaSocket);
+
+ connect(m_positionSource, &QNmeaPositionInfoSource::positionUpdated,
+ this, &QDeclarativePositionSource::positionUpdateReceived);
+
+ if (m_active && !m_singleUpdate) {
+ // Keep on updating even though source changed
+ QTimer::singleShot(0, this, SLOT(start()));
}
if (previousPositioningMethods != supportedPositioningMethods())
emit supportedPositioningMethodsChanged();
+}
- emit nmeaSourceChanged();
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::socketError(QAbstractSocket::SocketError error)
+{
+ delete m_nmeaSocket;
+ m_nmeaSocket = 0;
+
+ switch (error) {
+ case QAbstractSocket::UnknownSocketError:
+ m_sourceError = QDeclarativePositionSource::UnknownSourceError;
+ break;
+ case QAbstractSocket::SocketAccessError:
+ m_sourceError = QDeclarativePositionSource::AccessError;
+ break;
+ case QAbstractSocket::RemoteHostClosedError:
+ m_sourceError = QDeclarativePositionSource::ClosedError;
+ break;
+ default:
+ qWarning() << "Connection failed! QAbstractSocket::SocketError" << error;
+ m_sourceError = QDeclarativePositionSource::SocketError;
+ break;
+ }
+
+ emit sourceErrorChanged();
}
/*!
@@ -578,6 +659,7 @@ void QDeclarativePositionSource::positionUpdateReceived(const QGeoPositionInfo &
the user is switching location services to off. This object becomes invalid and should be deleted.
A new source can be declared later on to check whether the positioning backend is up again.
\li PositionSource.UnknownSourceError - An unidentified error occurred.
+ \li PositionSource.SocketError - An error occurred while connecting to an nmea source using a socket.
\endlist
*/
diff --git a/src/imports/positioning/qdeclarativepositionsource_p.h b/src/imports/positioning/qdeclarativepositionsource_p.h
index 70506c00..fc720301 100644
--- a/src/imports/positioning/qdeclarativepositionsource_p.h
+++ b/src/imports/positioning/qdeclarativepositionsource_p.h
@@ -45,12 +45,14 @@
#include "qdeclarativeposition_p.h"
#include <QtCore/QObject>
+#include <QtNetwork/QAbstractSocket>
#include <QtQml/QQmlParserStatus>
#include <QtPositioning/QGeoPositionInfoSource>
QT_BEGIN_NAMESPACE
class QFile;
+class QTcpSocket;
class QDeclarativePositionSource : public QObject, public QQmlParserStatus
{
@@ -83,7 +85,8 @@ public:
enum SourceError {
AccessError = QGeoPositionInfoSource::AccessError,
ClosedError = QGeoPositionInfoSource::ClosedError,
- UnknownSourceError = QGeoPositionInfoSource::UnknownSourceError
+ UnknownSourceError = QGeoPositionInfoSource::UnknownSourceError,
+ SocketError
};
Q_ENUMS(SourceError)
@@ -130,11 +133,14 @@ Q_SIGNALS:
private Q_SLOTS:
void positionUpdateReceived(const QGeoPositionInfo &update);
void sourceErrorReceived(const QGeoPositionInfoSource::Error error);
+ void socketConnected();
+ void socketError(QAbstractSocket::SocketError error);
private:
QGeoPositionInfoSource *m_positionSource;
QDeclarativePosition m_position;
PositioningMethods m_preferredPositioningMethods;
QFile *m_nmeaFile;
+ QTcpSocket *m_nmeaSocket;
QString m_nmeaFileName;
QUrl m_nmeaSource;
bool m_active;
diff --git a/src/positioning/doc/src/qml-position.qdoc b/src/positioning/doc/src/qml-position.qdoc
index 850bdd35..3ccac326 100644
--- a/src/positioning/doc/src/qml-position.qdoc
+++ b/src/positioning/doc/src/qml-position.qdoc
@@ -95,7 +95,19 @@ within the limits allowed by the platform, of the source of the
geographical data. Apart from tradtional sources such as GPS and cell data the positional data can be
sourced from a logfile which is in NMEA format.
-\l {http://en.wikipedia.org/wiki/NMEA}{NMEA} is a common text-based protocol for specifying navigational data. For convenience, the \l {PositionSource::nmeaSource}{nmeaSource} property is provided to enable QML applications to read NMEA data from a log file, the source will emit updates according to the time stamp of each NMEA sentence to produce a "replay" of the recorded data.
+\l {http://en.wikipedia.org/wiki/NMEA}{NMEA} is a common text-based
+protocol for specifying navigational data. For convenience, the \l
+{PositionSource::nmeaSource}{nmeaSource} property is provided to enable
+QML applications to read NMEA data from a log file or a TCP socket, the
+source will emit updates according to the time stamp of each NMEA sentence
+to produce a "replay" of the recorded data. To use a TCP socket set the
+"socket" uri scheme.
+
+\code
+PositionSource {
+ nmeaSource: "socket://127.0.0.1:12345"
+}
+\endcode