diff options
Diffstat (limited to 'src/location')
-rw-r--r-- | src/location/location.pro | 11 | ||||
-rw-r--r-- | src/location/qgeopositioninfosource.cpp | 8 | ||||
-rw-r--r-- | src/location/qgeopositioninfosource_npe_backend.cpp | 334 | ||||
-rw-r--r-- | src/location/qgeopositioninfosource_npe_backend_p.h | 105 |
4 files changed, 458 insertions, 0 deletions
diff --git a/src/location/location.pro b/src/location/location.pro index 2012769d..df4b9937 100644 --- a/src/location/location.pro +++ b/src/location/location.pro @@ -122,6 +122,17 @@ meego { } } +contains(config_test_jsondb, yes): contains(config_test_mtcore, yes) { + DEFINES += NPE_BACKEND + QT += jsondb-private + SOURCES += qgeopositioninfosource_npe_backend.cpp + PRIVATE_HEADERS += qgeopositioninfosource_npe_backend_p.h + unix{ + CONFIG += link_pkgconfig + PKGCONFIG += mtcore + } +} + HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS SOURCES += \ diff --git a/src/location/qgeopositioninfosource.cpp b/src/location/qgeopositioninfosource.cpp index e159085d..29517c81 100644 --- a/src/location/qgeopositioninfosource.cpp +++ b/src/location/qgeopositioninfosource.cpp @@ -57,6 +57,8 @@ # include "qgeopositioninfosource_maemo_p.h" #elif defined(Q_WS_MAEMO_5) # include "qgeopositioninfosource_maemo5_p.h" +#elif defined (NPE_BACKEND) +# include "qgeopositioninfosource_npe_backend_p.h" #endif #if defined (Q_WS_MEEGO) @@ -421,6 +423,12 @@ QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(QObject *par return geoclueSource; delete geoclueSource; #endif // GEOCLUE_MASTER_AVAILABLE +#elif defined(NPE_BACKEND) + QGeoPositionInfoSourceNpeBackend* npeBackendSource = new QGeoPositionInfoSourceNpeBackend(parent); + if (npeBackendSource->init()) + return npeBackendSource; + else + delete npeBackendSource; #endif // no good platform source, try plugins foreach (QGeoPositionInfoSourceFactory *f, QGeoPositionInfoSourcePrivate::pluginsSorted()) { diff --git a/src/location/qgeopositioninfosource_npe_backend.cpp b/src/location/qgeopositioninfosource_npe_backend.cpp new file mode 100644 index 00000000..a052ff26 --- /dev/null +++ b/src/location/qgeopositioninfosource_npe_backend.cpp @@ -0,0 +1,334 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosource_npe_backend_p.h" +#include <QtDebug> +#include <sys/stat.h> + + +// API for socket communication towards nld +const QString kstartUpdates = QLatin1String("startUpdates"); +const QString krequestUpdate = QLatin1String("requestUpdate"); +const QString kstopUpdates = QLatin1String("stopUpdates"); +const QString ksetUpdateInterval = QLatin1String("setUpdateInterval"); +const QString ksetPreferredMethod = QLatin1String("setPreferredMethod"); +const QString kgetMinimumUpdateInterval = QLatin1String("getMinimumUpdateInterval"); // Request +const QString kgetMinimumUpdateIntervalReply = QLatin1String("getMinimumUpdateIntervalReply"); // Response +const QString kgetSupportedMethods = QLatin1String("getSupportedMethods"); +const QString kgetSupportedMethodsReply = QLatin1String("getSupportedMethodsReply"); +const QString kgetLastKnownPosition = QLatin1String("getLastKnownPosition"); +const QString kgetLastKnownPositionReply = QLatin1String("getLastKnownPositionReply"); +const QString kpositionUpdate = QLatin1String("positionUpdate"); // Notification +const QString ksatelliteInfoUpdate = QLatin1String("satelliteInfoUpdate"); // Notification +const QString knmeaUpdate = QLatin1String("nmeaUpdate"); // Notification + +// Attributes for socket communication towards nld +const QString kinterval = QLatin1String("interval"); +const QString ksatelliteOnly = QLatin1String("satelliteOnly"); +const QString klatitude = QLatin1String("latitude"); +const QString klongitude = QLatin1String("longitude"); +const QString khorizontalAccuracy = QLatin1String("horizontalAccuracy"); +const QString kaltitude = QLatin1String("altitude"); +const QString kverticalAccuracy = QLatin1String("verticalAccuracy"); +const QString kgroundSpeed = QLatin1String("groundSpeed"); +const QString kverticalSpeed = QLatin1String("verticalSpeed"); +const QString kbearing = QLatin1String("bearing"); +const QString kmagneticVariation = QLatin1String("magneticVariation"); +const QString ktimestamp = QLatin1String("timestamp"); +const QString kmethod = QLatin1String("method"); +const QString kvalid = QLatin1String("valid"); + + + +QGeoPositionInfoSourceNpeBackend::QGeoPositionInfoSourceNpeBackend(QObject *parent): QGeoPositionInfoSource(parent) +{ + requestTimer = new QTimer(this); + QObject::connect(requestTimer, SIGNAL(timeout()), this, SLOT(requestTimerExpired())); + locationOngoing = false; +} + + +bool QGeoPositionInfoSourceNpeBackend::init() +{ + struct stat buf; + if (stat("/var/run/nld/nld.socket", &buf) == 0) { + mSocket = new QLocalSocket(this); + if (mSocket) { + connect(mSocket, SIGNAL(connected()), this, SLOT(onSocketConnected())); + connect(mSocket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected())); + mStream = new VariantStream(mSocket); + if (mStream) { + connect(mStream, SIGNAL(receive(const QVariantMap&)), this, SLOT(onStreamReceived(const QVariantMap&)), Qt::QueuedConnection); + } + mSocket->connectToServer("/var/run/nld/nld.socket"); + return(mSocket->waitForConnected(500)); // wait up to 0.5 seconds to get connected, otherwise return false + } + } + else + qDebug() << "stat fails for nld.socket"; + return(false); +} + + +QGeoPositionInfo QGeoPositionInfoSourceNpeBackend::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + // todo: test failed as nld does not respond yet; QEventloop forever.... + QEventLoop loop; // loop to wait for response from nld (asynchronous socket connection) + connect( this, SIGNAL(lastKnownPositionReceived()), &loop, SLOT(quit())); + QVariantMap action; + QVariantMap object; + action.insert(JsonDbString::kActionStr, kgetLastKnownPosition); + object.insert(ksatelliteOnly, fromSatellitePositioningMethodsOnly); + action.insert(JsonDbString::kDataStr, object); + mStream->send(action); + loop.exec(); // wait for signal lastKnownPositionReceived()sent by slot onStreamReceived + return(lastPosition); +} + + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceNpeBackend::supportedPositioningMethods() const +{ + QEventLoop loop; // loop to wait for response from nld (asynchronous socket connection) + connect( this, SIGNAL(supportedPositioningMethodsReceived()), &loop, SLOT(quit())); + QVariantMap action; + action.insert(JsonDbString::kActionStr, kgetSupportedMethods); + mStream->send(action); + loop.exec(); // wait for supportedPositioningMethodsReceived() signal sent by slot onStreamReceived + switch (supportedMethods){ + case QGeoPositionInfoSource::SatellitePositioningMethods: + return(QGeoPositionInfoSource::SatellitePositioningMethods); + case QGeoPositionInfoSource::NonSatellitePositioningMethods: + return(NonSatellitePositioningMethods); + case QGeoPositionInfoSource::AllPositioningMethods: + return(QGeoPositionInfoSource::AllPositioningMethods); + default: + qDebug() << "unsupported Method received from nld"; + } +} + + +void QGeoPositionInfoSourceNpeBackend::setUpdateInterval(int msec) +{ + QVariantMap action; + QEventLoop loop; // loop to wait for response from nld (asynchronous socket connection) + connect( this, SIGNAL(minimumUpdateIntervalReceived()), &loop, SLOT(quit())); + action.insert(JsonDbString::kActionStr, kgetMinimumUpdateInterval); + mStream->send(action); + loop.exec(); // wait for minimumUpdateIntervalReceived() signal sent by slot onStreamReceived + if (msec < minInterval) + msec = minInterval; + QVariantMap actionUpdate; + QVariantMap object; + actionUpdate.insert(JsonDbString::kActionStr, ksetUpdateInterval); + object.insert(kinterval, msec); + actionUpdate.insert(JsonDbString::kDataStr, object); + mStream->send(actionUpdate); + QGeoPositionInfoSource::setUpdateInterval(msec); +} + + +void QGeoPositionInfoSourceNpeBackend::setPreferredPositioningMethods(PositioningMethods sources) +{ + QGeoPositionInfoSource::setPreferredPositioningMethods(sources); + QVariantMap action; + QVariantMap object; + action.insert(JsonDbString::kActionStr, ksetPreferredMethod); + object.insert(kmethod, (uint)sources); + action.insert(JsonDbString::kDataStr, object); + mStream->send(action); +} + + +int QGeoPositionInfoSourceNpeBackend::minimumUpdateInterval() const +{ + QVariantMap action; + QEventLoop loop; // loop to wait for response from nld (asynchronous socket connection) + connect( this, SIGNAL(minimumUpdateIntervalReceived()), &loop, SLOT(quit())); + action.insert(JsonDbString::kActionStr, kgetMinimumUpdateInterval); + mStream->send(action); + loop.exec(); // wait for minimumUpdateIntervalReceived() signal sent by slot onStreamReceived + return(minInterval); +} + + +void QGeoPositionInfoSourceNpeBackend::startUpdates() +{ + locationOngoing = true; + QVariantMap action; + action.insert(JsonDbString::kActionStr, kstartUpdates); + mStream->send(action); +} + + +void QGeoPositionInfoSourceNpeBackend::stopUpdates() +{ + if ( !requestTimer->isActive() ) { + locationOngoing = false; + QVariantMap action; + action.insert(JsonDbString::kActionStr, kstopUpdates); + mStream->send(action); + } +} + + +void QGeoPositionInfoSourceNpeBackend::requestUpdate(int timeout) +{ + int minimumInterval = minimumUpdateInterval(); + // set reasonable timeout for the source if timeout is 0 + if (timeout == 0) + timeout = 5*minimumInterval; + // do not start request if timeout can not be fullfilled by the source + if (timeout < minimumInterval) { + emit updateTimeout(); + return; + } + // get position as accurate and fast as possible + if ( QGeoPositionInfoSource::updateInterval() != minimumInterval) { + QVariantMap actionUpdate; + QVariantMap object; + actionUpdate.insert(JsonDbString::kActionStr, ksetUpdateInterval); + object.insert(kinterval, minimumInterval); + actionUpdate.insert(JsonDbString::kDataStr, object); + mStream->send(actionUpdate); + } + if ( !QGeoPositionInfoSource::preferredPositioningMethods().testFlag(QGeoPositionInfoSource::AllPositioningMethods) ) + setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods); + // request the update only if no other regular session request is ongoing + if ( !locationOngoing ) { + QVariantMap action; + action.insert(JsonDbString::kActionStr, krequestUpdate); + mStream->send(action); + } + requestTimer->start(timeout); +} + + +void QGeoPositionInfoSourceNpeBackend::requestTimerExpired() +{ + emit updateTimeout(); + shutdownRequestSession(); +} + + + +void QGeoPositionInfoSourceNpeBackend::shutdownRequestSession() +{ + requestTimer->stop(); + // Restore updateInterval and preferedPositioningMethods from before Request Session + int minimumInterval = minimumUpdateInterval(); + if ( QGeoPositionInfoSource::updateInterval() != minimumInterval) + setUpdateInterval(QGeoPositionInfoSource::updateInterval()); + if ( !QGeoPositionInfoSource::preferredPositioningMethods().testFlag(QGeoPositionInfoSource::AllPositioningMethods) ) + setPreferredPositioningMethods(QGeoPositionInfoSource::preferredPositioningMethods()); +} + + +void QGeoPositionInfoSourceNpeBackend::onStreamReceived(const QVariantMap& map) +{ + // this slot handles the communication received from nld socket + if (map.contains(JsonDbString::kActionStr)) { + QString action = map.value(JsonDbString::kActionStr).toString(); + + if (action == kgetMinimumUpdateIntervalReply) { + QVariantMap tmp = map.value(JsonDbString::kDataStr).toMap(); + minInterval = tmp.value(kinterval).toInt(); + emit minimumUpdateIntervalReceived(); + } + + else if (action == kgetSupportedMethodsReply) { + QVariantMap tmp = map.value(JsonDbString::kDataStr).toMap(); + supportedMethods = tmp.value(kmethod).toUInt(); + emit supportedPositioningMethodsReceived(); + } + + else if (action == kgetLastKnownPositionReply) { + QVariantMap tmp = map.value(JsonDbString::kDataStr).toMap(); + bool valid = tmp.value(kvalid).toBool(); + if (valid) { + QGeoCoordinate coordinate; + coordinate.setLatitude(tmp.value(klatitude).toDouble()); + coordinate.setLongitude(tmp.value(klongitude).toDouble()); + lastPosition.setCoordinate(coordinate); + lastPosition.setTimestamp(tmp.value(ktimestamp).toDateTime()); + emit lastKnownPositionReceived(); + } + else + qDebug() << "invalid lastKnownPosition received from nld"; + } + + else if (action == kpositionUpdate) { + QVariantMap tmp = map.value(JsonDbString::kDataStr).toMap(); + QGeoPositionInfo update; + QGeoCoordinate coordinate; + coordinate.setLatitude(tmp.value(klatitude).toDouble()); + coordinate.setLongitude(tmp.value(klongitude).toDouble()); + coordinate.setAltitude(tmp.value(kaltitude).toDouble()); + if (coordinate.isValid()) { + update.setCoordinate(coordinate); + update.setAttribute(QGeoPositionInfo::HorizontalAccuracy, tmp.value(khorizontalAccuracy).toReal()); + update.setAttribute(QGeoPositionInfo::VerticalAccuracy, tmp.value(kverticalAccuracy).toReal()); + update.setAttribute(QGeoPositionInfo::GroundSpeed, tmp.value(kgroundSpeed).toReal()); + update.setAttribute(QGeoPositionInfo::VerticalSpeed, tmp.value(kverticalSpeed).toReal()); + update.setAttribute(QGeoPositionInfo::MagneticVariation, tmp.value(kmagneticVariation).toReal()); + update.setAttribute(QGeoPositionInfo::Direction, tmp.value(kbearing).toReal()); + QDateTime timestamp = tmp.value(ktimestamp).toDateTime(); + update.setTimestamp(timestamp); + emit positionUpdated(update); + if ( requestTimer->isActive() ) + shutdownRequestSession(); + } else { + qDebug() << "invalid position received from nld"; + } + } + } +} + + +void QGeoPositionInfoSourceNpeBackend::onSocketConnected() +{ + qDebug("Socket Connected!"); +} + + +void QGeoPositionInfoSourceNpeBackend::onSocketDisconnected() +{ + qDebug("Socket Disconnected!"); +} diff --git a/src/location/qgeopositioninfosource_npe_backend_p.h b/src/location/qgeopositioninfosource_npe_backend_p.h new file mode 100644 index 00000000..ff518796 --- /dev/null +++ b/src/location/qgeopositioninfosource_npe_backend_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPOSITIONINFOSOURCE_NPE_BACKEND_H +#define QGEOPOSITIONINFOSOURCE_NPE_BACKEND_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qgeopositioninfosource.h> +#include <mtcore/variantstream.h> +#include <private/jsondb-strings_p.h> +#include <qlocalsocket.h> +#include <qeventloop.h> +#include <qtimer.h> + +Q_USE_JSONDB_NAMESPACE + +class QGeoPositionInfoSourceNpeBackend : public QGeoPositionInfoSource +{ + Q_OBJECT + +public: + QGeoPositionInfoSourceNpeBackend(QObject *parent = 0); + bool init(); + void setUpdateInterval(int interval); + void setPreferredPositioningMethods(PositioningMethods sources); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + int minimumUpdateInterval() const; + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout = 5000); + +private: + QLocalSocket* mSocket; + VariantStream* mStream; + int minInterval; + uint supportedMethods; + QGeoPositionInfo lastPosition; + bool locationOngoing; + QTimer* requestTimer; + void shutdownRequestSession(); + +Q_SIGNALS: + void minimumUpdateIntervalReceived(); + void supportedPositioningMethodsReceived(); + void lastKnownPositionReceived(); + +private Q_SLOTS: + void onStreamReceived(const QVariantMap& map); + void onSocketConnected(); + void onSocketDisconnected(); + void requestTimerExpired(); +}; + +#endif // QGEOPOSITIONINFOSOURCE_NPE_BACKEND_H |