Hi, i've hacked together a slightly incomplete GpsdPositionInfoSource. This allows to use qt mobility location on a gpsd based system (e.g. ordinary linux desktops).
It's slightly incomplete as it doesn't support changing the update interval nor the timeout on requestUpdate. Both are things i don't need/use in the app i wrote this for (cacheme). The code is public domain and uses the json parser from http://nilier.blogspot.com/2010/08/json-parser-class-for-qt.html Have fun, Till
/**************************************************************************** ** GpsdPositionInfoSource ** (c) 2011 by Till Harbaum <t...@harbaum.org> ** This code is public domain, do what you want with it ****************************************************************************/ // Based infos from: // http://gpsd.berlios.de/client-howto.html // http://doc.qt.nokia.com/qtmobility-1.0-tp/qgeopositioninfosource.html #include <QDebug> #include <QByteArray> #include <QStringList> #include <math.h> #include "gpsdpositioninfosource.h" #include "json.h" #ifndef NAN #define NAN (0.0/0.0) #endif qreal GpsdPositionInfoSource::getReal(const QMap<QString, QVariant> &map, const QString &name) { // make sure that key exists if(!map.contains(name)) return NAN; QVariant variant = map.value(name); // make sure value is variant of correkt type if(QVariant::String != variant.type()) return NAN; // extract string and convert to float return variant.toString().toFloat(); } void GpsdPositionInfoSource::setAttribute(QGeoPositionInfo &info, QGeoPositionInfo::Attribute attr, const QMap<QString, QVariant> &map, const QString &name) { qreal value = getReal(map, name); if(!isnan(value)) info.setAttribute(attr, value); } void GpsdPositionInfoSource::parse(const QString &str) { bool ok; // feed reply into json parser // json is a QString containing the data to convert QVariant result = Json::parse(str, ok); if(!ok) { qDebug() << __FUNCTION__ << "Json deconding failed."; return; } // we expect a qvariantmap if(QVariant::Map != result.type()) { qDebug() << __FUNCTION__ << "Unexpected result type:" << result.type(); return; } QMap<QString, QVariant> map = result.toMap(); // extract reply class QString classStr = map.value("class").toString(); if(!classStr.compare("VERSION")) { qDebug() << "Connected to GPSD:"; qDebug() << "Release:" << map.value("release").toString(); qDebug() << "Revision:" << map.value("rev").toString(); qDebug() << "Protocol version:" << map.value("proto_major").toString() + "." + map.value("proto_minor").toString(); } else if(!classStr.compare("TPV")) { // TPV is the most interesting string for us m_lastKnown = QGeoPositionInfo(); int mode = map.value("mode").toInt(); if(mode > 0) { QGeoCoordinate coo(getReal(map, "lat"), getReal(map, "lon")); if(mode == 3) coo.setAltitude(getReal(map, "alt")); m_lastKnown.setCoordinate(coo); } setAttribute(m_lastKnown, QGeoPositionInfo::Direction, map, "track"); setAttribute(m_lastKnown, QGeoPositionInfo::VerticalSpeed, map, "climb"); setAttribute(m_lastKnown, QGeoPositionInfo::GroundSpeed, map, "speed"); setAttribute(m_lastKnown, QGeoPositionInfo::VerticalAccuracy, map, "epv"); setAttribute(m_lastKnown, QGeoPositionInfo::HorizontalAccuracy, map, "epv"); // horizontal error in lat or long qreal epx = getReal(map, "epx"); qreal epy = getReal(map, "epy"); if(!isnan(epx) && !isnan(epy)) m_lastKnown.setAttribute(QGeoPositionInfo::HorizontalAccuracy, epx>epy?epx:epy); QDateTime time; time.setTime_t(getReal(map, "time")); m_lastKnown.setTimestamp(time); emit positionUpdated( m_lastKnown ); } } void GpsdPositionInfoSource::readData() { // split reply into seperate strings at newline QStringList data = QString::fromUtf8(m_tcpSocket->readAll()).split('\n'); for(int i=0;i<data.size();i++) if(!data[i].trimmed().isEmpty()) parse(data[i].trimmed()); } void GpsdPositionInfoSource::displayError(QAbstractSocket::SocketError) { qDebug() << __FUNCTION__ << "Error: " << m_tcpSocket->errorString(); } GpsdPositionInfoSource::GpsdPositionInfoSource(QObject *parent) : QGeoPositionInfoSource(parent) { qDebug() << __FUNCTION__; // connect to gpsd m_tcpSocket = new QTcpSocket(this); connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readData())); connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); m_tcpSocket->connectToHost("localhost", 2947); } GpsdPositionInfoSource::~GpsdPositionInfoSource() { qDebug() << __FUNCTION__; m_tcpSocket->close(); } void GpsdPositionInfoSource::setUpdateInterval(int msec) { int interval = msec; if (interval != 0) interval = qMax(msec, minimumUpdateInterval()); QGeoPositionInfoSource::setUpdateInterval(interval); } void GpsdPositionInfoSource::startUpdates() { // request info from gpsd QString request = "?WATCH={\"enable\":true,\"json\":true}"; m_tcpSocket->write(request.toUtf8()); } void GpsdPositionInfoSource::stopUpdates() { // ask gpsd to stop sending data QString request = "?WATCH={\"enable\":false}"; m_tcpSocket->write(request.toUtf8()); } void GpsdPositionInfoSource::requestUpdate(int) { emit positionUpdated( m_lastKnown ); } QGeoPositionInfo GpsdPositionInfoSource::lastKnownPosition(bool) const { // the bool value does not matter since we only use satellite positioning return m_lastKnown; } QGeoPositionInfoSource::PositioningMethods GpsdPositionInfoSource::supportedPositioningMethods() const { return SatellitePositioningMethods; } int GpsdPositionInfoSource::minimumUpdateInterval() const { return 1000; }
/**************************************************************************** ** GpsdPositionInfoSource ** (c) 2011 by Till Harbaum <t...@harbaum.org> ** This code is public domain, do what you want with it ****************************************************************************/ #ifndef GPSDPOSITIONINFOSOURCE_H #define GPSDPOSITIONINFOSOURCE_H #include <QObject> #include <QTcpSocket> #include <QGeoPositionInfoSource> QTM_USE_NAMESPACE class GpsdPositionInfoSource : public QGeoPositionInfoSource { Q_OBJECT public: GpsdPositionInfoSource(QObject *parent = 0); ~GpsdPositionInfoSource(); void setUpdateInterval(int msec); QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; PositioningMethods supportedPositioningMethods() const; int minimumUpdateInterval() const; public slots: void startUpdates(); void stopUpdates(); void requestUpdate(int timeout = 0); private slots: void readData(); void displayError(QAbstractSocket::SocketError); private: qreal getReal(const QMap<QString, QVariant> &, const QString &); void setAttribute(QGeoPositionInfo &, QGeoPositionInfo::Attribute, const QMap<QString, QVariant> &, const QString &); void parse(const QString &); QTcpSocket *m_tcpSocket; QGeoPositionInfo m_lastKnown; }; #endif
_______________________________________________ Qt-mobility-feedback mailing list Qt-mobility-feedback@qt.nokia.com http://lists.qt.nokia.com/mailman/listinfo/qt-mobility-feedback