summaryrefslogtreecommitdiff
path: root/enhanced-position-service/src/enhanced-position.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'enhanced-position-service/src/enhanced-position.cpp')
-rw-r--r--enhanced-position-service/src/enhanced-position.cpp617
1 files changed, 617 insertions, 0 deletions
diff --git a/enhanced-position-service/src/enhanced-position.cpp b/enhanced-position-service/src/enhanced-position.cpp
new file mode 100644
index 0000000..85ff4ff
--- /dev/null
+++ b/enhanced-position-service/src/enhanced-position.cpp
@@ -0,0 +1,617 @@
+/**************************************************************************
+* @licence app begin@
+*
+* SPDX-License-Identifier: MPL-2.0
+*
+* \ingroup EnhancedPositionService
+* \author Marco Residori <marco.residori@xse.de>
+*
+* \copyright Copyright (C) 2014, XS Embedded GmbH
+*
+* \license
+* This Source Code Form is subject to the terms of the
+* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+* this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* @licence end@
+**************************************************************************/
+
+#include <stdio.h>
+#include "enhanced-position.h"
+#include "positioning-constants.h"
+#include "log.h"
+
+DLT_IMPORT_CONTEXT(gCtx);
+
+EnhancedPosition* EnhancedPosition::mpSelf = 0;
+
+static DBus::Variant variant_double(double d)
+{
+ DBus::Variant variant;
+ DBus::MessageIter iter=variant.writer();
+ iter << d;
+ return variant;
+}
+
+static DBus::Variant variant_uint16(uint16_t i)
+{
+ DBus::Variant variant;
+ DBus::MessageIter iter=variant.writer();
+ iter << i;
+ return variant;
+}
+
+static DBus::Variant variant_int32(int32_t i)
+{
+ DBus::Variant variant;
+ DBus::MessageIter iter=variant.writer();
+ iter << i;
+ return variant;
+}
+
+static DBus::Variant variant_string(std::string s)
+{
+ DBus::Variant variant;
+ DBus::MessageIter iter=variant.writer();
+ iter << s;
+ return variant;
+}
+
+EnhancedPosition::EnhancedPosition(DBus::Connection & connection, const char * path)
+ : DBus::ObjectAdaptor(connection, path)
+{
+ mpSelf = this;
+}
+
+EnhancedPosition::~EnhancedPosition()
+{
+ mpSelf = 0;
+}
+
+::DBus::Struct< uint16_t, uint16_t, uint16_t, std::string > EnhancedPosition::GetVersion()
+{
+ ::DBus::Struct< uint16_t, uint16_t, uint16_t, std::string > Version;
+
+ Version._1 = 2;
+ Version._2 = 0;
+ Version._3 = 0;
+ Version._4 = std::string("04-06-2013");
+
+ return Version;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetData(const std::vector< uint16_t >& valuesToReturn)
+{
+ std::map< uint16_t, ::DBus::Variant > Data;
+
+ TGNSSPosition pos;
+ TGNSSCourse course;
+
+ bool isPosRequested = false;
+ bool isCourseRequested = false;
+
+ for (int i = 0; i < valuesToReturn.size(); i++)
+ {
+ if ((valuesToReturn[i] == POS_LATITUDE) ||
+ (valuesToReturn[i] == POS_LONGITUDE) ||
+ (valuesToReturn[i] == POS_ALTITUDE))
+ {
+ //if any of the three IDs above is set, then gnssSimpleGetPosition will have to be called
+ isPosRequested = true;
+ }
+
+ if ((valuesToReturn[i] == POS_HEADING) ||
+ (valuesToReturn[i] == POS_SPEED) ||
+ (valuesToReturn[i] == POS_CLIMB ))
+ {
+ //if any of the three IDs above is set, then gnssSimpleGetCourse will have to be called
+ isCourseRequested = true;
+ }
+ }
+
+ if(isPosRequested)
+ {
+ if(gnssSimpleGetPosition(&pos))
+ {
+ if (pos.validityBits && GNSS_POSITION_LATITUDE_VALID)
+ {
+ Data[POS_LATITUDE] = variant_double(pos.latitude);
+ }
+
+ if (pos.validityBits && GNSS_POSITION_LONGITUDE_VALID)
+ {
+ Data[POS_LONGITUDE] = variant_double(pos.longitude);
+ }
+
+ if (pos.validityBits && GNSS_POSITION_ALTITUDE_VALID)
+ {
+ Data[POS_ALTITUDE] = variant_int32(pos.altitude);
+ }
+ }
+ }
+
+ if(isCourseRequested)
+ {
+ if(gnssSimpleGetCourse(&course))
+ {
+ if (course.validityBits && GNSS_COURSE_SPEED_VALID)
+ {
+ Data[POS_HEADING] = variant_int32(course.heading);
+ }
+
+ if (course.validityBits && GNSS_COURSE_CLIMB_VALID)
+ {
+ Data[POS_SPEED] = variant_double(course.speed);
+ }
+
+ if (course.validityBits && GNSS_COURSE_HEADING_VALID)
+ {
+ Data[POS_CLIMB] = variant_int32(course.climb);
+ }
+ }
+ }
+
+ return Data;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetPosition()
+{
+ std::map< uint16_t, ::DBus::Variant > Position;
+ TGNSSPosition pos;
+ TGNSSCourse course;
+
+ if (gnssSimpleGetPosition(&pos))
+ {
+ if (pos.validityBits && GNSS_POSITION_LATITUDE_VALID)
+ {
+ Position[POS_LATITUDE] = variant_double(pos.latitude);
+ }
+
+ if (pos.validityBits && GNSS_POSITION_LONGITUDE_VALID)
+ {
+ Position[POS_LONGITUDE] = variant_double(pos.longitude);
+ }
+
+ if (pos.validityBits && GNSS_POSITION_ALTITUDE_VALID)
+ {
+ Position[POS_ALTITUDE] = variant_int32(pos.altitude);
+ }
+ }
+
+ if(gnssSimpleGetCourse(&course))
+ {
+ if (pos.validityBits && GNSS_COURSE_SPEED_VALID)
+ {
+ Position[POS_HEADING] = variant_int32(course.heading);
+ }
+
+ if (pos.validityBits && GNSS_COURSE_CLIMB_VALID)
+ {
+ Position[POS_SPEED] = variant_double(course.speed);
+ }
+
+ if (pos.validityBits && GNSS_COURSE_HEADING_VALID)
+ {
+ Position[POS_CLIMB] = variant_int32(course.climb);
+ }
+ }
+
+ return Position;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetRotationRate()
+{
+ std::map< uint16_t, ::DBus::Variant > RotationRate;
+
+ throw DBus::ErrorNotSupported("Method not supported yet");
+
+ return RotationRate;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetAccuracy()
+{
+ std::map< uint16_t, ::DBus::Variant > Accuracy;
+
+ throw DBus::ErrorNotSupported("Method not supported yet");
+
+ return Accuracy;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetSatelliteInfo()
+{
+ std::map< uint16_t, ::DBus::Variant > SatelliteInfo;
+
+ throw DBus::ErrorNotSupported("Method not supported yet");
+
+ return SatelliteInfo;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetStatus()
+{
+ std::map< uint16_t, ::DBus::Variant > Status;
+
+ throw DBus::ErrorNotSupported("Method not supported yet");
+
+ return Status;
+}
+
+std::map< uint16_t, ::DBus::Variant > EnhancedPosition::GetTime()
+{
+ std::map< uint16_t, ::DBus::Variant > Time;
+
+ throw DBus::ErrorNotSupported("Method not supported yet");
+
+ return Time;
+}
+
+void EnhancedPosition::cbPosition(const TGNSSPosition pos[], uint16_t numElements)
+{
+ bool latChanged = false;
+ bool lonChanged = false;
+ bool altChanged = false;
+
+ std::vector< uint16_t > position;
+
+ if (pos == NULL || numElements < 1)
+ {
+ LOG_ERROR_MSG(gCtx,"cbPosition failed!");
+ return;
+ }
+
+ for (int i = 0; i< numElements; i++)
+ {
+ LOG_INFO(gCtx,"Position Update[%d/%d]: lat=%f lon=%f alt=%f",
+ i+1,
+ numElements,
+ pos[i].latitude,
+ pos[i].longitude,
+ pos[i].altitude);
+
+ if (latChanged == false)
+ {
+ latChanged = (pos[i].validityBits && GNSS_POSITION_LATITUDE_VALID);
+ }
+
+ if (lonChanged == false)
+ {
+ lonChanged = (pos[i].validityBits && GNSS_POSITION_LONGITUDE_VALID);
+ }
+
+ if (altChanged == false)
+ {
+ altChanged = (pos[i].validityBits && GNSS_POSITION_ALTITUDE_VALID);
+ }
+
+ }
+
+ //in a real product, the coordinates would be used for dead-reckoning.
+ //in this proof of concept, the client application is simply notified
+ //about changes of latitude, longitude and/or altitude
+ std::vector< uint16_t > changedValues;
+ std::vector<uint16_t>::iterator it;
+ it = changedValues.begin();
+
+ if (latChanged)
+ {
+ it = changedValues.insert(it,POS_LATITUDE);
+ }
+
+ if (lonChanged)
+ {
+ it = changedValues.insert(it,POS_LONGITUDE);
+ }
+
+ if (altChanged)
+ {
+ it = changedValues.insert(it,POS_ALTITUDE);
+ }
+
+ if (!mpSelf)
+ {
+ LOG_ERROR_MSG(gCtx,"Null pointer!");
+ return;
+ }
+
+ //notify clients
+ mpSelf->PositionUpdate(changedValues);
+}
+
+void EnhancedPosition::cbCourse(const TGNSSCourse course[], uint16_t numElements)
+{
+ bool speedChanged = false;
+ bool headingChanged = false;
+ bool climbChanged = false;
+
+ if (course == NULL || numElements < 1)
+ {
+ LOG_ERROR_MSG(gCtx,"cbCourse failed!");
+ return;
+ }
+
+ for (int i = 0; i < numElements; i++)
+ {
+ LOG_INFO(gCtx,"Course Update[%d/%d]: speed=%f heading=%f climb=%f",
+ i+1,
+ numElements,
+ course[i].speed,
+ course[i].heading,
+ course[i].climb);
+
+ if (speedChanged == false)
+ {
+ speedChanged = (course[i].validityBits && GNSS_COURSE_SPEED_VALID);
+ }
+
+ if (headingChanged == false)
+ {
+ headingChanged = (course[i].validityBits && GNSS_COURSE_HEADING_VALID);
+ }
+
+ if (climbChanged == false)
+ {
+ climbChanged = (course[i].validityBits && GNSS_COURSE_CLIMB_VALID);
+ }
+ }
+
+ //in a real product, the course would be used for dead-reckoning.
+ //in this proof of concept, the client application is simply notified
+ //about changes of speed, heading and/or climb
+ std::vector< uint16_t > changedValues;
+ std::vector<uint16_t>::iterator it;
+ it = changedValues.begin();
+
+ if (speedChanged)
+ {
+ it = changedValues.insert(it,POS_SPEED);
+ }
+
+ if (headingChanged)
+ {
+ it = changedValues.insert(it,POS_HEADING);
+ }
+
+ if (climbChanged)
+ {
+ it = changedValues.insert(it,POS_CLIMB);
+ }
+
+ if (!mpSelf)
+ {
+ LOG_ERROR_MSG(gCtx,"Null pointer!");
+ return;
+ }
+
+ //notify clients
+ mpSelf->PositionUpdate(changedValues);
+}
+
+void EnhancedPosition::cbAccuracy(const TGNSSAccuracy accuracy[], uint16_t numElements)
+{
+ //satellite info
+ bool usedSatellitesChanged = false;
+ bool trackedSatellitesChanged = false;
+ bool visibleSatellitesChanged = false;
+
+ //status
+ bool fixStatusChanged = false;
+ bool fixTypeBitsChanged = false;
+
+ //accuracy
+ bool pdopChanged = false;
+ bool hdopChanged = false;
+ bool vdopChanged = false;
+ bool sigmaLatitudeChanged = false;
+ bool sigmaLongitudeChanged = false;
+ bool sigmaAltitudeChanged = false;
+
+ if (accuracy == NULL || numElements < 1)
+ {
+ LOG_ERROR_MSG(gCtx,"cbAccuracy failed!");
+ return;
+ }
+
+ for (int i = 0; i< numElements; i++)
+ {
+ LOG_INFO(gCtx,"Accuracy Update[%d/%d]: usedSatellites=%d trackedSatellites=%d visibleSatellites=%d",
+ i+1,
+ numElements,
+ accuracy[i].usedSatellites,
+ accuracy[i].trackedSatellites,
+ accuracy[i].visibleSatellites);
+
+ LOG_INFO(gCtx,"Accuracy Update[%d/%d]: fixStatus=%d fixTypeBits=0x%08X",
+ i+1,
+ numElements,
+ accuracy[i].fixStatus,
+ accuracy[i].fixTypeBits);
+
+ LOG_INFO(gCtx,"Accuracy Update[%d/%d]: pdop=%f hdop=%f vdop=%f \
+ sigmaLatitude=%f sigmaLongitude=%f sigmaAltitude=%f",
+ i+1,
+ numElements,
+ accuracy[i].pdop,
+ accuracy[i].hdop,
+ accuracy[i].vdop,
+ accuracy[i].sigmaLatitude,
+ accuracy[i].sigmaLongitude,
+ accuracy[i].sigmaAltitude);
+
+ if (usedSatellitesChanged == false)
+ {
+ usedSatellitesChanged = (accuracy[i].validityBits && GNSS_ACCURACY_USAT_VALID);
+ }
+
+ if (trackedSatellitesChanged == false)
+ {
+ trackedSatellitesChanged = (accuracy[i].validityBits && GNSS_ACCURACY_TSAT_VALID);
+ }
+
+ if (visibleSatellitesChanged == false)
+ {
+ visibleSatellitesChanged = (accuracy[i].validityBits && GNSS_ACCURACY_VSAT_VALID);
+ }
+
+ if (fixStatusChanged == false)
+ {
+ fixStatusChanged = (accuracy[i].validityBits && GNSS_ACCURACY_STAT_VALID);
+ }
+
+ if (fixTypeBitsChanged == false)
+ {
+ fixTypeBitsChanged = (accuracy[i].validityBits && GNSS_ACCURACY_TYPE_VALID);
+ }
+
+ if (pdopChanged == false)
+ {
+ pdopChanged = (accuracy[i].validityBits && GNSS_ACCURACY_PDOP_VALID);
+ }
+
+ if (hdopChanged == false)
+ {
+ hdopChanged = (accuracy[i].validityBits && GNSS_ACCURACY_HDOP_VALID);
+ }
+
+ if (vdopChanged == false)
+ {
+ vdopChanged = (accuracy[i].validityBits && GNSS_ACCURACY_VDOP_VALID);
+ }
+
+ if (sigmaLatitudeChanged == false)
+ {
+ sigmaLatitudeChanged = (accuracy[i].validityBits && GNSS_ACCURACY_SLAT_VALID);
+ }
+
+ if (sigmaLongitudeChanged == false)
+ {
+ sigmaLongitudeChanged = (accuracy[i].validityBits && GNSS_ACCURACY_SLON_VALID);
+ }
+
+ if (sigmaAltitudeChanged == false)
+ {
+ sigmaAltitudeChanged = (accuracy[i].validityBits && GNSS_ACCURACY_SALT_VALID);
+ }
+ }
+
+ //in a real product, the accuracy would be used for dead-reckoning.
+ //in this proof of concept, the client application is simply notified
+ //about accuracy changes
+ std::vector<uint16_t>::iterator it;
+
+ std::vector< uint16_t > changedSatelliteInfoValues;
+ it = changedSatelliteInfoValues.begin();
+
+ if (usedSatellitesChanged)
+ {
+ it = changedSatelliteInfoValues.insert(it,POS_USED_SATELLITES);
+ }
+
+ if (trackedSatellitesChanged)
+ {
+ it = changedSatelliteInfoValues.insert(it,POS_TRACKED_SATELLITES);
+ }
+
+ if (visibleSatellitesChanged)
+ {
+ it = changedSatelliteInfoValues.insert(it,POS_VISIBLE_SATELLITES);
+ }
+
+ //todo: handle other field-changes here (accuracy and status)
+
+ if (!mpSelf)
+ {
+ LOG_ERROR_MSG(gCtx,"Null pointer!");
+ return;
+ }
+
+ mpSelf->SatelliteInfoUpdate(changedSatelliteInfoValues);
+
+ //todo: send other notifications
+ //mpSelf->AccuracyUpdate(changedAccuracyValues);
+ //mpSelf->StatusUpdate(changedStatusValues);
+}
+
+void EnhancedPosition::cbSatelliteDetail(const TGNSSSatelliteDetail satelliteDetail[], uint16_t numElements)
+{
+ if (satelliteDetail == NULL || numElements < 1)
+ {
+ LOG_ERROR_MSG(gCtx,"cbSatelliteDetail failed!");
+ return;
+ }
+
+ for (int i = 0; i<numElements; i++)
+ {
+ LOG_INFO(gCtx,"SatelliteDetail Update[%d/%d]: satelliteId=%d azimuth=%d elevation=%d SNR=%d",
+ i+1,
+ numElements,
+ satelliteDetail[i].satelliteId,
+ satelliteDetail[i].azimuth,
+ satelliteDetail[i].elevation,
+ satelliteDetail[i].SNR);
+ }
+
+ if (!mpSelf)
+ {
+ LOG_ERROR_MSG(gCtx,"Null pointer!");
+ return;
+ }
+
+ //todo: notify clients
+ //mpSelf->SatelliteInfoUpdate(changedValues);
+}
+
+bool EnhancedPosition::checkMajorVersion(int expectedMajor)
+{
+ int major = -1;
+
+ gnssGetVersion(&major, 0, 0);
+
+ if (major != expectedMajor)
+ {
+ LOG_ERROR(gCtx,"Wrong API version: gnssGetVersion returned unexpected value %d != %d",
+ major,
+ expectedMajor);
+
+ return false;
+ }
+
+ return true;
+}
+
+void EnhancedPosition::run()
+{
+ if(!checkMajorVersion(2))
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ if(!gnssInit())
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ if(!gnssSimpleInit())
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ LOG_INFO_MSG(gCtx,"Starting EnhancedPosition dispatcher...");
+
+ gnssSimpleRegisterPositionCallback(&cbPosition);
+ gnssSimpleRegisterCourseCallback(&cbCourse);
+ gnssExtendedRegisterAccuracyCallback(&cbAccuracy);
+ gnssExtendedRegisterSatelliteDetailCallback(&cbSatelliteDetail);
+}
+
+void EnhancedPosition::shutdown()
+{
+ LOG_INFO_MSG(gCtx,"shutting down...");
+
+ gnssSimpleDeregisterPositionCallback(&cbPosition);
+ gnssSimpleDeregisterCourseCallback(&cbCourse);
+ gnssExtendedDeregisterAccuracyCallback(&cbAccuracy);
+ gnssExtendedDeregisterSatelliteDetailCallback(&cbSatelliteDetail);
+ gnssSimpleDestroy();
+ gnssDestroy();
+}
+
+