summaryrefslogtreecommitdiff
path: root/test/poi-service/poi-contentaccess-module/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/poi-service/poi-contentaccess-module/main.cpp')
-rw-r--r--test/poi-service/poi-contentaccess-module/main.cpp947
1 files changed, 947 insertions, 0 deletions
diff --git a/test/poi-service/poi-contentaccess-module/main.cpp b/test/poi-service/poi-contentaccess-module/main.cpp
new file mode 100644
index 0000000..fa5efa2
--- /dev/null
+++ b/test/poi-service/poi-contentaccess-module/main.cpp
@@ -0,0 +1,947 @@
+/**
+* @licence app begin@
+* SPDX-License-Identifier: MPL-2.0
+*
+* \copyright Copyright (C) 2013-2014, PCA Peugeot Citroen
+*
+* \file main.cpp
+*
+* \brief This file is part of the poi proof of concept.
+*
+* \author Philippe Colliot <philippe.colliot@mpsa.com>
+*
+* \version 1.1
+*
+* This Source Code Form is subject to the terms of the
+* Mozilla Public License (MPL), 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/.
+*
+* For further information see http://www.genivi.org/.
+*
+* List of changes:
+* 10-02-2014, Philippe Colliot, refinement and migration to the new repository
+* <date>, <name>, <description of change>
+*
+* @licence end@
+*/
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <iostream>
+#include <cmath>
+#include <typeinfo>
+#include <getopt.h>
+
+#include "poi-contentaccess-module-class.h"
+
+#include <QtGui/QApplication>
+#include <QTranslator>
+#include "mainwindow.h"
+
+#include <QSettings>
+
+static const char* contentAccessModule_SERVICE_NAME = "org.genivi.poiservice.POIContentAccessModule";
+static const char* contentAccessModule_OBJECT_PATH = "/org/genivi/poiservice/POIContentAccessModule";
+static const char* poiContentAccess_SERVICE_NAME = "org.genivi.poiservice.POIContentAccess";
+static const char* poiContentAccess_OBJECT_PATH = "/org/genivi/poiservice/POIContentAccess";
+
+// SQL requests
+static const char* SQL_REQUEST_GET_AVAILABLE_CATEGORIES = "SELECT Id,name FROM poicategory WHERE Id IN (SELECT poicategory_Id FROM belongsto GROUP BY poicategory_Id);";
+static const char* SQL_REQUEST_GET_VALIDATE_CATEGORIES = "SELECT Id,name FROM poicategory;";
+static const char* SQL_REQUEST_GET_CATEGORY_ATTRIBUTES = "SELECT Id,name FROM poiattribute WHERE Id IN (SELECT poiattribute_Id FROM hasattribute WHERE poicategory_Id IS ";
+static const char* SQL_REQUEST_GET_AVAILABLE_AREA = "SELECT leftlongitude,bottomlatitude,rightlongitude,toplatitude FROM availablearea;";
+static const char* SQL_REQUEST_GET_PARENT_CATEGORIES = "SELECT parentId FROM poicategorykinship WHERE childId IS ";
+static const char* SQL_REQUEST_GET_CHILD_CATEGORIES = "SELECT childId FROM poicategorykinship WHERE parentId IS ";
+static const char* SQL_REQUEST_GET_CATEGORY_ICONS = "SELECT url,format FROM iconset WHERE Id IS (SELECT iconset_Id FROM isdisplayedas WHERE poicategory_Id IS ";
+
+// DBus instances
+static DBus::Glib::BusDispatcher *dispatcher;
+static DBus::Connection *dbusConnection;
+static contentAccessModuleServer *servercontentAccessModule;
+static poiContentAccess *clientpoiContentAccess;
+
+
+// class poiContentAccess
+
+poiContentAccess::poiContentAccess(DBus::Connection &connection)
+ : DBus::ObjectProxy(connection,poiContentAccess_OBJECT_PATH,poiContentAccess_SERVICE_NAME)
+ {
+
+ }
+
+poiContentAccess::~poiContentAccess()
+ {
+
+ }
+
+// class contentAccessModuleServer
+
+contentAccessModuleServer::contentAccessModuleServer(DBus::Connection &connection, const char* poiDatabaseFileName)
+ : DBus::ObjectAdaptor(connection, contentAccessModule_OBJECT_PATH)
+ {
+ std::string sqlQuery; //SQL request on database
+ std::ostringstream strStream; //temporary stream used for transformation into string
+ vector<vector<string> > query_result, additionnal_query_result;
+ vector<string> query_line, additionnal_query_line;
+ size_t index,sub_index;
+ category_attribute_t attribute;
+ uint16_t value;
+ uint16_t parent,child;
+
+ //version is hard coded
+ DBus_version::version_t version;
+ version.major = 1;
+ version.minor = 0;
+ version.micro = 0;
+ version.date = "19-12-2012";
+ m_version.set(version);
+
+ //status
+ m_poiSearchHandle = INVALID_HANDLE;
+ m_camId = INVALID_HANDLE;
+ m_searchStatus = GENIVI_POISERVICE_NOT_STARTED;
+
+ //database
+ mp_database = new Database(poiDatabaseFileName);
+
+ m_availableCategories = 0;
+
+ // all the pois and the related stuff are included into the database at the startup
+ // so we can update some tables into the constructor
+
+ // retrieve the available categories (the ones that have at least one record)
+ query_result = mp_database->query(SQL_REQUEST_GET_AVAILABLE_CATEGORIES);
+ if (query_result.empty())
+ {
+ onError(); //database is not well populated
+ //todo something with table ?
+ }
+ else
+ { // Id,name
+ m_availableCategories = query_result.size(); //store the number of categories
+ for (index = 0; index < m_availableCategories; index++)
+ {
+ // read the result of the query and store it
+ query_line = query_result.at(index);
+ fromString<uint16_t>(value,query_line[0], std::dec);
+ m_availableCategoryTable[index].id = value;
+
+ // retrieve the associated icons (for the moment, just one)
+ sqlQuery = SQL_REQUEST_GET_CATEGORY_ICONS;
+ strStream.str("");
+ strStream << value;
+ sqlQuery += strStream.str();
+ sqlQuery += ");";
+ additionnal_query_result = mp_database->query(sqlQuery.c_str());
+ if (additionnal_query_result.empty())
+ {
+ onError(); //database is not well populated
+ //todo something with table ?
+ }
+ else
+ {
+ additionnal_query_line = additionnal_query_result.at(0);
+ m_availableCategoryTable[index].icon = additionnal_query_line[0] + '.' + additionnal_query_line[1];
+ }
+
+ m_availableCategoryTable[index].name = query_line[1];
+
+ // retrieve the associated attributes
+ sqlQuery = SQL_REQUEST_GET_CATEGORY_ATTRIBUTES;
+ strStream.str("");
+ strStream << m_availableCategoryTable[index].id;
+ sqlQuery += strStream.str();
+ sqlQuery += ");";
+ additionnal_query_result = mp_database->query(sqlQuery.c_str());
+ if (additionnal_query_result.empty())
+ {
+ onError(); //database is not well populated
+ //todo something with table ?
+ }
+ else
+ {
+ for (sub_index = 0; sub_index <additionnal_query_result.size(); sub_index++)
+ {
+ additionnal_query_line = additionnal_query_result.at(sub_index);
+ fromString<ushort>(attribute.id,additionnal_query_line[0], std::dec);
+ attribute.name = additionnal_query_line[1];
+ attribute.isSearched = false;
+ m_availableCategoryTable[index].attributeList.push_back(attribute);
+ }
+ }
+ m_availableCategoryTable[index].top_level = true; //this POC only manages predefined categories
+ m_availableCategoryTable[index].isSearch = false; //for the moment no categories selected
+ }
+ }
+
+ //retrieve the parents of the categories
+ //root category is the only one that is its own parent
+ for (index = 0; index < m_availableCategories; index++)
+ {
+ sqlQuery = SQL_REQUEST_GET_PARENT_CATEGORIES;
+ strStream.str("");
+ strStream << m_availableCategoryTable[index].id;
+ sqlQuery += strStream.str();
+ sqlQuery += ";";
+ query_result = mp_database->query(sqlQuery.c_str());
+ if (query_result.empty())
+ {
+ onError(); //database is not well populated
+ //todo something with table ?
+ }
+ else
+ {
+ for (parent=0;parent<query_result.size();parent++)
+ {
+ query_line = query_result.at(parent);
+ fromString<uint16_t>(value,query_line[0], std::dec);
+ if (index == value)
+ m_rootCategory = index; //child is parent, so it's the root
+ m_availableCategoryTable[index].parentList.push_back(value);
+ }
+ }
+ }
+
+ //retrieve the children of the categories
+ for (index = 0; index < m_availableCategories; index++)
+ {
+ sqlQuery = SQL_REQUEST_GET_CHILD_CATEGORIES;
+ strStream.str("");
+ strStream << m_availableCategoryTable[index].id;
+ sqlQuery += strStream.str();
+ sqlQuery += ";";
+ query_result = mp_database->query(sqlQuery.c_str());
+ if (query_result.empty())
+ {
+ //no child
+ }
+ else
+ {
+ for (child=0;child<query_result.size();child++)
+ {
+ query_line = query_result.at(child);
+ fromString<uint16_t>(value,query_line[0], std::dec);
+ m_availableCategoryTable[index].childList.push_back(value);
+ }
+ }
+ }
+
+ //retrieve the available area into the database
+ query_result = mp_database->query(SQL_REQUEST_GET_AVAILABLE_AREA);
+ if (query_result.empty())
+ {
+ onError(); //database is not well populated
+ //todo something with table ?
+ }
+ else
+ {
+ // read the result of the query, for the moment only the first area !
+ query_line = query_result.at(0);
+ fromString<double>(m_leftBottomLocation.latitude,query_line[0], std::dec);
+ fromString<double>(m_leftBottomLocation.longitude,query_line[1], std::dec);
+ fromString<double>(m_rightTopLocation.latitude,query_line[2], std::dec);
+ fromString<double>(m_rightTopLocation.longitude,query_line[3], std::dec);
+ }
+ m_centerLocation.latitude = 48.85792; //by default center of Paris
+ m_centerLocation.longitude = 2.3383145;
+ m_centerLocation.altitude = 0;
+
+ }
+
+contentAccessModuleServer::~contentAccessModuleServer()
+ {
+ delete mp_database;
+ }
+
+DBus_version::DBus_version_t contentAccessModuleServer::GetVersion()
+ {
+ return(m_version.getDBus());
+ }
+
+void contentAccessModuleServer::SetLanguage(const std::string& languageCode, const std::string& countryCode)
+ {
+ m_languageCode = languageCode;
+ m_countryCode = countryCode;
+ mp_HMI->on_SetLanguage(languageCode,countryCode);
+ }
+
+void contentAccessModuleServer::PoiSearchStarted(const uint8_t& poiSearchHandle, const uint16_t& maxSize, const DBus_geoCoordinate3D::DBus_geoCoordinate3D_t& location, const std::vector< DBus_categoryRadius::DBus_categoryRadius_t >& poiCategories, const std::vector< DBus_attributeDetails::DBus_attributeDetails_t >& poiAttributes, const std::string& inputString, const uint16_t& sortOption)
+ {
+ uint16_t index,sub_index,category_index;
+ bool isCategoryFound, isAttributeFound;
+ DBus_attributeDetails attribDet;
+ DBus_attributeDetails::attributeDetails_t attribDetails;
+ DBus_geoCoordinate3D geoCoord;
+ DBus_geoCoordinate3D::geoCoordinate3D_t geoCoordinate;
+ DBus_categoryRadius catRad;
+ DBus_categoryRadius::categoryRadius_t catRadius;
+
+ //todo: limit the search to maxSize, manage sortOption
+
+ if (m_poiSearchHandle != INVALID_HANDLE)
+ // new search launched before end of the last one
+ sendDBusError("org.genivi.poiprovider.poiSearch.Error.HandleNotAvailable"); //to be discussed !
+ else
+ {
+ //preliminary reset of flags for categories
+ for (index=0;index<m_availableCategories;index++)
+ {
+ m_availableCategoryTable[index].isSearch = false;
+ //reset flags for all the attributes of the category
+ for (category_index=0;category_index<((m_availableCategoryTable[index]).attributeList).size();category_index++)
+ (m_availableCategoryTable[index]).attributeList.at(category_index).isSearched =false;
+ }
+
+ //now scan the flags to set and set the flag into the m_availableCategoryTable
+ for (index=0;index<poiCategories.size();index++)
+ {
+ catRad.setDBus(poiCategories.at(index));
+ catRadius = catRad.get();
+ sub_index = 0;
+ isCategoryFound = false;
+ do
+ {
+ if (catRadius.id == (m_availableCategoryTable[sub_index].alias_id))
+ { //the content access server is using alias !
+ isCategoryFound = true;
+ m_availableCategoryTable[sub_index].isSearch = true;
+ m_availableCategoryTable[sub_index].radius = (catRadius.radius)*10; //get the radius (unit is 10 m)
+ m_availableCategoryTable[sub_index].angle = calculateAngle(m_availableCategoryTable[sub_index].radius);
+ }
+ else
+ ++sub_index;
+ } while((isCategoryFound == false) && (sub_index<m_availableCategories));
+ }
+
+ //reset flags for all the attributes of the categories into the database
+ for (index=0;index<m_availableCategories;index++)
+ {
+ for (category_index=0;category_index<((m_availableCategoryTable[index]).attributeList).size();category_index++)
+ (m_availableCategoryTable[index]).attributeList.at(category_index).isSearched =false;
+ }
+
+ //now scan the flags to be set
+ for (index=0;index<poiAttributes.size();index++)
+ {
+ sub_index = 0;
+ isAttributeFound = false;
+ attribDet.setDBus(poiAttributes.at(index));
+ attribDetails = attribDet.get();
+ if ( isCategoryAvailable(attribDetails.poiCategory,&category_index) == true)
+ { //category found into the database!
+ if (m_availableCategoryTable[category_index].isSearch)
+ { //category selected for the search
+ for (sub_index=0;sub_index<(m_availableCategoryTable[category_index].attributeList.size());sub_index++)
+ { //check attribute by name
+ if ((m_availableCategoryTable[category_index].attributeList.at(sub_index)).name == attribDetails.attribute.name)
+ (m_availableCategoryTable[category_index].attributeList.at(sub_index)).isSearched =true;
+ }
+ }
+ }
+ }
+
+ m_poiSearchHandle = poiSearchHandle;
+ geoCoord.setDBus(location);
+ geoCoordinate = geoCoord.get();
+ m_centerLocation.latitude = geoCoordinate.latitude;
+ m_centerLocation.longitude = geoCoordinate.longitude;
+ m_centerLocation.altitude = geoCoordinate.altitude;
+ m_searchStatus = GENIVI_POISERVICE_SEARCHING;
+ //sortOption is not used
+ //maxSize is not used
+ m_totalSize = searchAroundALocation(m_centerLocation,&inputString);
+ m_searchStatus = GENIVI_POISERVICE_FINISHED;
+ }
+ }
+
+void contentAccessModuleServer::PoiSearchCanceled(const uint8_t& poiSearchHandle)
+ {
+ if ((m_poiSearchHandle == INVALID_HANDLE) || (poiSearchHandle != m_poiSearchHandle))
+ // try to cancel an unavailable handle
+ sendDBusError("org.genivi.poiprovider.poiSearch.Error.HandleNotAvailable"); //to be discussed !
+ else
+ {
+ m_poiSearchHandle = INVALID_HANDLE;
+ m_totalSize = 0;
+ m_poiTable.clear();
+ }
+ }
+
+void contentAccessModuleServer::ResultListRequested(const uint8_t& camId, const uint8_t& poiSearchHandle, const std::vector< std::string >& attributes, uint16_t& statusValue, uint16_t& resultListSize, std::vector< DBus_poiCAMDetails::DBus_poiCAMDetails_t >& resultList)
+ {
+
+ //this method is supposed to check the camId, but into the POC, it's the HMI that declares the CAM (for the moment)
+
+ //todo: manage attributes
+ if ((m_poiSearchHandle == INVALID_HANDLE) || (poiSearchHandle != m_poiSearchHandle))
+ // to do send an error message
+ sendDBusError("org.genivi.poiprovider.poiSearch.Error.HandleNotAvailable"); //to be discussed !
+ else
+ {
+ resultListSize = m_totalSize;
+ resultList.insert(resultList.end(),m_poiTable.begin(),m_poiTable.end());
+ statusValue = m_searchStatus;
+ m_poiSearchHandle = INVALID_HANDLE; //search is considered to be finished ?
+ }
+ }
+
+std::vector< DBus_searchResultDetails::DBus_searchResultDetails_t > contentAccessModuleServer::PoiDetailsRequested(const std::vector< uint32_t >& source_id)
+ {
+ std::vector< DBus_searchResultDetails::DBus_searchResultDetails_t > return_value;
+ DBus_searchResultDetails searchDet;
+ DBus_searchResultDetails::searchResultDetails_t searchDetails;
+ uint16_t index,indexPOIList;
+ bool isPOIFound;
+
+ return_value.clear();
+ for (index=0;index<source_id.size();index++)
+ { //scan the list of poi to detail
+ isPOIFound = false;
+ //scan the table
+ indexPOIList=0;
+ while((isPOIFound == false) && (indexPOIList<m_poiDetailsTable.size()))
+ {
+ searchDet.setDBus(m_poiDetailsTable.at(indexPOIList));
+ searchDetails = searchDet.get();
+ if (searchDetails.details.id == source_id.at(index))
+ {
+ isPOIFound = true;
+ return_value.push_back(m_poiDetailsTable.at(indexPOIList));
+ }
+ else
+ ++indexPOIList;
+ }
+ }
+ return (return_value);
+ }
+
+// Specific methods
+
+DBus::Variant contentAccessModuleServer::createVariantString(std::string str)
+{
+ DBus::Variant var;
+ DBus::MessageIter iter = var.writer();
+ iter.append_string(str.c_str());
+ return var;
+}
+
+DBus::Variant contentAccessModuleServer::createVariantUint16(uint16_t value)
+{
+ DBus::Variant var;
+ DBus::MessageIter iter = var.writer();
+ iter.append_uint16(value);
+ return var;
+}
+
+void contentAccessModuleServer::connectToHMI(MainWindow *w)
+{
+ mp_HMI = w;
+}
+
+void contentAccessModuleServer::connectCAM(uint8_t camId)
+{
+ m_camId = camId;
+}
+
+void contentAccessModuleServer::disconnectCAM()
+{
+ m_camId = INVALID_HANDLE;
+}
+
+std::vector<DBus_CAMcategory::DBus_CAMcategory_t> contentAccessModuleServer::getCategories()
+{
+ std::vector< DBus_CAMcategory::DBus_CAMcategory_t > return_value;
+ DBus_CAMcategory CAMcat;
+ DBus_CAMcategory::CAMcategory_t CAMCategory;
+ DBus_categoryAttribute::categoryAttribute_t categoryAttribute;
+ DBus_categoryOperator::categoryOperator_t categoryOperator;
+ size_t index,sub_index;
+
+ for (index=0;index<m_availableCategories;index++)
+ {
+ CAMCategory.details.name = m_availableCategoryTable[index].name;
+ for (sub_index=0;sub_index<m_availableCategoryTable[index].parentList.size();sub_index++)
+ {
+ CAMCategory.details.parents_id.push_back(m_availableCategoryTable[index].parentList.at(sub_index));
+ }
+ CAMCategory.details.media = "";
+ CAMCategory.details.icons = m_availableCategoryTable[index].icon;
+ CAMCategory.details.short_desc = "";
+ //scan the attributes
+ CAMCategory.attributes.clear();
+ for (sub_index=0;sub_index<m_availableCategoryTable[index].attributeList.size();sub_index++)
+ {
+ categoryAttribute.name = (m_availableCategoryTable[index].attributeList.at(sub_index)).name;
+ categoryAttribute.type = 0;
+ categoryAttribute.oper.clear();
+ categoryOperator.id = GENIVI_POISERVICE_EQUAL;
+ categoryOperator.name = "EQUAL";
+ categoryAttribute.oper.push_back(categoryOperator);
+ CAMCategory.attributes.push_back(categoryAttribute);
+ }
+
+ CAMcat.set(CAMCategory);
+ return_value.push_back(CAMcat.getDBus());
+ }
+
+ return(return_value);
+}
+
+void contentAccessModuleServer::setCategoriesID(std::vector<uint16_t> categoryIDList)
+{
+ size_t index;
+ for (index=0;index<m_availableCategories;index++)
+ { //consider the given ID are in the same order as the registered ones
+ m_availableCategoryTable[index].alias_id = categoryIDList.at(index);
+ }
+}
+
+std::string contentAccessModuleServer::getCAMName()
+{
+ std::string str = contentAccessModule_SERVICE_NAME;
+ return(str);
+}
+
+uint8_t contentAccessModuleServer::getCAMId()
+{
+ return(m_camId);
+}
+
+uint16_t contentAccessModuleServer::searchAroundALocation(DBus_geoCoordinate3D::geoCoordinate3D_t location,const std::string* inputString)
+ {
+ uint16_t index;
+ uint16_t total_size;
+ DBus_geoCoordinate3D::geoCoordinate3D_t left_bottom_location,right_top_location;
+
+ total_size = 0;
+ m_poiTable.clear(); //clean the table of poi
+
+ for (index=0;index<m_availableCategories;index++)
+ {
+ if (m_availableCategoryTable[index].isSearch)
+ {
+ left_bottom_location.latitude = location.latitude - m_availableCategoryTable[index].angle;
+ left_bottom_location.longitude = location.longitude - m_availableCategoryTable[index].angle;
+ right_top_location.latitude = location.latitude + m_availableCategoryTable[index].angle;
+ right_top_location.longitude = location.longitude + m_availableCategoryTable[index].angle;
+ total_size += searchPOIRequest(index, *inputString,left_bottom_location,right_top_location);
+ }
+ }
+
+ return(total_size);
+ }
+
+uint16_t contentAccessModuleServer::searchPOIRequest(uint16_t categoryIndex, std::string search_string, DBus_geoCoordinate3D::geoCoordinate3D_t left_bottom_location,DBus_geoCoordinate3D::geoCoordinate3D_t right_top_location)
+ {
+ std::string sqlQuery; //SQL request on database
+ vector<vector<string> > sqlQueryResult; //result of the query on database
+ vector<string> sqlQueryLine;
+ std::ostringstream strStream; //temporary stream used for transformation into string
+ size_t index,sub_index,attribute_index;
+ DBus_poiCAMDetails poiCAMDet;
+ DBus_poiCAMDetails::poiCAMDetails_t poi; //source_id, name, category, location, distance, attributes
+ DBus_poiAttribute::poiAttribute_t poiAttrib;
+ DBus_searchResultDetails poiDet;
+ DBus_searchResultDetails::searchResultDetails_t poiDetails; //details(unique id, name, lat, lon, alt), categories, attributes(name, type, value)
+ std::string name;
+
+ name = m_availableCategoryTable[categoryIndex].name;
+
+ sqlQuery = "SELECT name,segment,latitude,longitude,altitude";
+ for (attribute_index=0;attribute_index<m_availableCategoryTable[categoryIndex].attributeList.size();attribute_index++)
+ {
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).isSearched == true)
+ {
+ sqlQuery += ",";
+ sqlQuery += (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ }
+
+ }
+
+ sqlQuery += " FROM poi WHERE (Id IN (SELECT poi_Id FROM belongsto,poicategory WHERE (belongsto.poicategory_Id = poicategory.Id) AND (poicategory.name = '";
+ sqlQuery += name;
+ sqlQuery += "'))) AND ((latitude > ";
+ strStream.str(""); //to clean before !
+ strStream << left_bottom_location.latitude;
+ sqlQuery += strStream.str();
+ sqlQuery += ") AND (latitude < ";
+ strStream.str(""); //to clean before !
+ strStream << right_top_location.latitude;
+ sqlQuery += strStream.str();
+ sqlQuery += ")) AND ((longitude > ";
+ strStream.str(""); //to clean before !
+ strStream << left_bottom_location.longitude;
+ sqlQuery += strStream.str();
+ sqlQuery += ") AND (longitude < ";
+ strStream.str(""); //to clean before !
+ strStream << right_top_location.longitude;
+ sqlQuery += strStream.str();
+ sqlQuery += ")) AND (name LIKE '%";
+ sqlQuery += search_string;
+ sqlQuery += "%');";
+ sqlQueryResult = mp_database->query(sqlQuery.c_str());
+
+ //populate the tables of poi
+ poi.category = categoryIndex; //category
+ poiDetails.categories.push_back(m_availableCategoryTable[categoryIndex].alias_id); //categories for the table of details
+
+ for (index=0;index<sqlQueryResult.size();index++)
+ {
+ sqlQueryLine = sqlQueryResult.at(index);
+ fromString<uint32_t>(poi.source_id,sqlQueryLine[1], std::dec); //source_id
+ fromString<uint32_t>(poiDetails.details.id,sqlQueryLine[1], std::dec); //source_id for the table of details
+ poi.name = sqlQueryLine[0]; //name
+ poiDetails.details.name = sqlQueryLine[0]; //name for the table of details
+ fromString<double>(poi.location.latitude,sqlQueryLine[2], std::dec); //location lat
+ fromString<double>(poi.location.longitude,sqlQueryLine[3], std::dec); //location lon
+ fromString<int>(poi.location.altitude,sqlQueryLine[4], std::dec); //location alt
+
+ fromString<double>(poiDetails.details.latitude,sqlQueryLine[2], std::dec); //location lat for the table of details
+ fromString<double>(poiDetails.details.longitude,sqlQueryLine[3], std::dec); //location lon for the table of details
+ fromString<int>(poiDetails.details.altitude,sqlQueryLine[4], std::dec); //location alt for the table of details
+
+ sub_index = 5; //next index to scan into the query line
+ for (attribute_index=0;attribute_index<m_availableCategoryTable[categoryIndex].attributeList.size();attribute_index++)
+ {
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).isSearched == true)
+ {
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).id == ATTRIBUTE_SOURCE)
+ {
+ poiAttrib.name = (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ poiAttrib.type = GENIVI_POISERVICE_STRING;
+ poiAttrib.value = sqlQueryLine[sub_index];
+ poi.attributes.push_back(poiAttrib);
+ poiDetails.attributes.push_back(poiAttrib); //for the table of details
+ }
+ else
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).id == ATTRIBUTE_WEBSITE)
+ {
+ poiAttrib.name = (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ poiAttrib.type = GENIVI_POISERVICE_STRING;
+ poiAttrib.value = sqlQueryLine[sub_index];
+ poi.attributes.push_back(poiAttrib);
+ poiDetails.attributes.push_back(poiAttrib); //for the table of details
+ }
+ else
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).id == ATTRIBUTE_PHONE)
+ {
+ poiAttrib.name = (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ poiAttrib.type = GENIVI_POISERVICE_STRING;
+ poiAttrib.value = sqlQueryLine[sub_index];
+ poi.attributes.push_back(poiAttrib);
+ poiDetails.attributes.push_back(poiAttrib); //for the table of details
+ }
+ else
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).id == ATTRIBUTE_STARS)
+ {
+ poiAttrib.name = (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ poiAttrib.type = GENIVI_POISERVICE_INTEGER;
+ poiAttrib.value = sqlQueryLine[sub_index];
+ poi.attributes.push_back(poiAttrib);
+ poiDetails.attributes.push_back(poiAttrib); //for the table of details
+ }
+ else
+ if ((m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).id == ATTRIBUTE_OPENINGHOURS)
+ {
+ poiAttrib.name = (m_availableCategoryTable[categoryIndex].attributeList.at(attribute_index)).name;
+ poiAttrib.type = GENIVI_POISERVICE_STRING;
+ poiAttrib.value = sqlQueryLine[sub_index];
+ poi.attributes.push_back(poiAttrib);
+ poiDetails.attributes.push_back(poiAttrib); //for the table of details
+ }
+ sub_index++;
+ }
+
+ }
+
+ //calculate distance from the center location
+ poi.distance = calculateDistance(m_centerLocation,poi.location);
+ poiCAMDet.set(poi);
+ m_poiTable.push_back(poiCAMDet.getDBus());
+ poiDet.set(poiDetails);
+ m_poiDetailsTable.push_back(poiDet.getDBus());
+ }
+
+ return(sqlQueryResult.size());
+ }
+
+void contentAccessModuleServer::sendDBusError(const char* message)
+ {
+ throw DBus::ErrorFailed(message);
+ }
+
+void contentAccessModuleServer::onError()
+{
+}
+
+bool contentAccessModuleServer::isCategoryAvailable(uint16_t id, uint16_t *category_id)
+{
+ bool isFound = false;
+ uint16_t index = 0;
+ do
+ {
+ if (m_availableCategoryTable[index].alias_id == id)
+ {
+ *category_id = index;
+ isFound = true;
+ }
+ else
+ ++index;
+ } while ((isFound==false) && (index < m_availableCategories));
+
+ return(isFound);
+}
+
+uint32_t contentAccessModuleServer::calculateDistance(const DBus_geoCoordinate3D::geoCoordinate3D_t origin, const DBus_geoCoordinate3D::geoCoordinate3D_t target)
+ {
+ //this piece of software is based on an haversine formula given by:
+ // - Doctors Rick and Peterson, The Math Forum
+ // http://mathforum.org/dr.math/
+ // haversine of angle A is (1-cos(A))/2 that is equal to sin^2(A/2)
+
+ //earth is considered to be a perfect spĥere, in order to simplify calculation
+ const double PI = 4.0*atan(1.0);
+ const double earth=6378137; //IUGG value for the equatorial radius of the Earth in m
+ DBus_geoCoordinate3D::geoCoordinate3D_t pointA, pointB;
+ double buffer;
+
+ pointA.latitude = origin.latitude * (PI/180);
+ pointA.longitude = origin.longitude * (PI/180);
+ pointB.latitude = target.latitude * (PI/180);
+ pointB.longitude = target.longitude * (PI/180);
+
+ buffer= pow(sin((pointA.latitude-pointB.latitude)/2.0),2.0)+cos(pointA.latitude)*cos(pointB.latitude)*pow(sin((pointA.longitude-pointB.longitude)/2),2);
+ buffer = 2*atan2(sqrt(buffer),sqrt(1.0-buffer));
+ buffer=earth*buffer;
+ return ((uint32_t) buffer); //return distance in meters
+ }
+
+double contentAccessModuleServer::calculateAngle(const uint32_t radius)
+ {
+ //N is the point on the sphere for the origin
+ //M is a point of the sphere at the distance radius (NM = radius)
+ //O is the center of the earth
+ //ON=OM so the triangle is isosceles
+ //alpha is the angle ON,OM
+ //beta is the angle NM,NO
+ //OM*sin(alpha)=NM*sin(beta)
+ //alpha+beta+beta=PI (because of isoceles)
+ //beta=(PI-alpha)/2
+ //sin(beta) = cos(alpha/2)
+ //sin(alpha)=2*sin(alpha/2)*cos(alpha/2)
+ //alpha=2*arcsin(NM/(2*OM))
+
+ //earth is considered to be a perfect spĥere, in order to simplify calculation
+ const double PI = 4.0*atan(1.0);
+ const double earth=6378137; //IUGG value for the equatorial radius of the Earth in m
+ double angle;
+ angle=2*asin(radius/(2*earth));
+ angle = (angle*180)/PI; //in degrees
+ return(angle);
+ }
+
+const char* program_name; //file to sink outputs
+
+/**
+ * \fn is_readable (const std::string & file)
+ * \brief Check if file can be opened.
+ *
+ * \param const std::string & file -name of the file
+ * \return true if file readable.
+ */
+bool is_readable( const std::string & file )
+{
+ std::ifstream fi( file.c_str() );
+ return !fi.fail();
+}
+
+/**
+ * \fn print_usage (FILE* stream, int exit_code)
+ * \brief Display the available options.
+ *
+ * \param const FILE* stream -name of stream to use
+ * \param int exit_code -exit code
+ * \return void.
+ */
+void print_usage (FILE* stream, int exit_code)
+{
+ fprintf (stream, "Use: %s options [database]\n",program_name);
+ fprintf (stream,
+ " -h --help Display this message.\n"
+ " -f --file database Open the database.\n"
+ " -i --internationalisation database language(en,jp) Open the database, international version.\n");
+ exit (exit_code);
+}
+
+/**
+ * \fn int main (int argc , char** argv)
+ * \brief POI Server which implements the components of POI Service (search, contentaccess and content access module).
+ *
+ * \param int argc
+ * \param char** argv
+ * \return EXIT_SUCCESS, EXIT_FAILURE.
+ */
+
+
+int main(int argc , char** argv )
+{
+ GMainLoop * mainloop ;
+
+ // Set the global C and C++ locale to the user-configured locale,
+ // so we can use std::cout with UTF-8, via Glib::ustring, without exceptions.
+ std::locale::global(std::locale(""));
+
+ //index used for argument analysis
+ int next_option;
+
+ /* Valid letters for short options. */
+ const char* const short_options = "hfi:";
+ /* Valid string for long options. */
+ const struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "file", 1, NULL, 'f' },
+ { "internationalisation", 2, NULL, 'i' },
+ { NULL, 0, NULL, 0 } /* Always at the end of the table. */
+ };
+ char* database_filename = NULL; //database filename passed as first argument
+
+
+ program_name = argv[0];
+
+ do {
+ next_option = getopt_long (argc, argv, short_options,
+ long_options, NULL);
+ switch (next_option)
+ {
+ case 'h': /* -h --help */
+ print_usage (stdout, 0);
+ break;
+ case 'f': /* -f --file database */
+ database_filename = argv[2];
+ if (!is_readable(database_filename))
+ print_usage (stderr, 1);
+ else
+ {
+ QApplication a(argc, argv);
+ QTranslator translator;
+ translator.load("POIPOC_en.ts","../POIPOCCommon/"); // english by default
+ a.installTranslator(&translator);
+ MainWindow mainWindow;
+
+ // creating the dispatcher
+ dispatcher = new DBus::Glib::BusDispatcher();
+ DBus::default_dispatcher = dispatcher;
+ dispatcher->attach(NULL);
+
+ // create a connection on the session bus
+ dbusConnection = new DBus::Connection(DBus::Connection::SessionBus());
+ dbusConnection->setup(dispatcher);
+
+ // create the server for contentAccessModule
+ dbusConnection->request_name(contentAccessModule_SERVICE_NAME);
+ servercontentAccessModule=new contentAccessModuleServer(*dbusConnection,database_filename);
+
+ // connect it to the HMI panel
+ mainWindow.ConnectTocontentAccessModuleServer(servercontentAccessModule);
+
+ // connect the HMI panel to it
+ servercontentAccessModule->connectToHMI(&mainWindow);
+
+ // create a client for poiContentAccess
+ clientpoiContentAccess = new poiContentAccess(*dbusConnection);
+
+ // connect it to the HMI panel
+ mainWindow.ConnectTopoiContentAccessClient(clientpoiContentAccess);
+
+ // Create a new GMainLoop with default context and initial state of "not running "
+ mainloop = g_main_loop_new (g_main_context_default() , FALSE );
+
+ // loop listening
+ mainWindow.InitUi();
+ mainWindow.show();
+
+ return a.exec();
+
+ // clean memory
+ delete servercontentAccessModule;
+ delete dbusConnection;
+ delete dispatcher;
+ }
+ break;
+ case 'i': /* -i --internationalisation database language */
+ database_filename = argv[2];
+ if (!is_readable(database_filename))
+ print_usage (stderr, 1);
+ else
+ {
+ QApplication a(argc, argv);
+ QTranslator translator;
+ QString language(argv[3]);
+ if (translator.load("poi-contentaccess-module_"+ language,"../poi-common/"))
+ {
+ a.installTranslator(&translator);
+ MainWindow mainWindow;
+
+ // creating the dispatcher
+ dispatcher = new DBus::Glib::BusDispatcher();
+ DBus::default_dispatcher = dispatcher;
+ dispatcher->attach(NULL);
+
+ // create a connection on the session bus
+ dbusConnection = new DBus::Connection(DBus::Connection::SessionBus());
+ dbusConnection->setup(dispatcher);
+
+ // create the server for contentAccessModule
+ dbusConnection->request_name(contentAccessModule_SERVICE_NAME);
+ servercontentAccessModule=new contentAccessModuleServer(*dbusConnection,database_filename);
+
+ // connect it to the HMI panel
+ mainWindow.ConnectTocontentAccessModuleServer(servercontentAccessModule);
+
+ // connect the HMI panel to it
+ servercontentAccessModule->connectToHMI(&mainWindow);
+
+ // create a client for poiContentAccess
+ clientpoiContentAccess = new poiContentAccess(*dbusConnection);
+
+ // connect it to the HMI panel
+ mainWindow.ConnectTopoiContentAccessClient(clientpoiContentAccess);
+
+ // Create a new GMainLoop with default context and initial state of "not running "
+ mainloop = g_main_loop_new (g_main_context_default() , FALSE );
+
+ // loop listening
+ mainWindow.InitUi();
+ mainWindow.show();
+
+ int ret = a.exec();
+
+ // clean memory
+ delete servercontentAccessModule;
+ delete dbusConnection;
+ delete dispatcher;
+ }
+ else
+ {
+ print_usage (stderr, 1);
+ }
+ }
+ break;
+ case '?': /* Invalid option. */
+ print_usage (stderr, 1);
+ case -1: /* End of options. */
+ break;
+ default: /* Error */
+ print_usage (stderr, 1);
+ }
+ }
+ while (next_option != -1);
+
+ return EXIT_SUCCESS;
+}
+