/** * @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 * * \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 * , , * * @licence end@ */ #include #include #include #include #include #include #include #include #include #include #include "poi-contentaccess-module-class.h" #include #include #include #include #include "mainwindow.h" #include static const char* contentAccessModule_SERVICE_NAME = "org.genivi.navigation.poiservice.POIContentAccessModule"; static const char* contentAccessModule_OBJECT_PATH = "/org/genivi/poiservice/POIContentAccessModule"; static const char* poiContentAccess_SERVICE_NAME = "org.genivi.navigation.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 > query_result, additionnal_query_result; vector query_line, additionnal_query_line; size_t index,sub_index; category_attribute_common_t attribute; categoryId_t value; categoryId_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); // language code is hard coded m_languageCode = "eng"; m_countryCode = "USA"; m_scriptCode = "Latn"; //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(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 (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(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(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(m_leftBottomLocation.latitude,query_line[0], std::dec); fromString(m_leftBottomLocation.longitude,query_line[1], std::dec); fromString(m_rightTopLocation.latitude,query_line[2], std::dec); fromString(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::SetLocale(const std::string& languageCode, const std::string& countryCode, const std::string &scriptCode) { m_languageCode = languageCode; m_countryCode = countryCode; m_scriptCode = scriptCode; mp_HMI->on_SetLocale(languageCode,countryCode,scriptCode); } void contentAccessModuleServer::GetLocale(std::string& languageCode, std::string& countryCode, std::string& scriptCode) { languageCode = m_languageCode; countryCode = m_countryCode; scriptCode = m_scriptCode; } std::vector< ::DBus::Struct< std::string, std::string , std::string> > contentAccessModuleServer::GetSupportedLocales() { std::vector< ::DBus::Struct< std::string, std::string, std::string > > ret; ::DBus::Struct< std::string, std::string, std::string > en_US { "eng","USA", "Latn" }; ::DBus::Struct< std::string, std::string, std::string > fr_FR { "fra","FRA", "Latn" }; ret.push_back(en_US); ret.push_back(fr_FR); return ret; } std::vector< DBus_categoryIdName::DBus_categoryIdName_t > contentAccessModuleServer::GetAvailableCategories() { } categoryId_t contentAccessModuleServer::GetRootCategory() { } std::vector< DBus_categoryIdLevel::DBus_categoryIdLevel_t > contentAccessModuleServer::GetChildrenCategories(const categoryId_t& category) { } std::vector< DBus_categoryIdLevel::DBus_categoryIdLevel_t > contentAccessModuleServer::GetParentCategories(const categoryId_t& category) { } categoryId_t contentAccessModuleServer::createCategory(const DBus_CAMcategory::DBus_CAMcategory_t& category) { } void contentAccessModuleServer::removeCategories(const std::vector< categoryId_t >& categories) { } void contentAccessModuleServer::addPOIs(const categoryId_t& unique_id, const std::vector< DBus_PoiAddedDetails::DBus_PoiAddedDetails_t >& poiList) { } void contentAccessModuleServer::removePOIs(const std::vector< poiId_t >& ids) { } void contentAccessModuleServer::PoiSearchStarted(const handleId_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 int32_t& sortOption) { uint16_t index,sub_index; categoryId_t 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& attributes, int32_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< poiId_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 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 categoryIDList) { size_t index; for (index=0;index > sqlQueryResult; //result of the query on database vector 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_indexquery(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(poi.source_id,sqlQueryLine[1], std::dec); //source_id fromString(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(poi.location.latitude,sqlQueryLine[2], std::dec); //location lat fromString(poi.location.longitude,sqlQueryLine[3], std::dec); //location lon fromString(poi.location.altitude,sqlQueryLine[4], std::dec); //location alt fromString(poiDetails.details.location.latitude,sqlQueryLine[2], std::dec); //location lat for the table of details fromString(poiDetails.details.location.longitude,sqlQueryLine[3], std::dec); //location lon for the table of details fromString(poiDetails.details.location.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_indexattach(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, 2); } } else { print_usage (stderr, 3); } return EXIT_SUCCESS; }