diff options
6 files changed, 1260 insertions, 55 deletions
diff --git a/src/navigation/navigation-core/CMakeLists.txt b/src/navigation/navigation-core/CMakeLists.txt index c9fad47..65e2e1b 100644 --- a/src/navigation/navigation-core/CMakeLists.txt +++ b/src/navigation/navigation-core/CMakeLists.txt @@ -45,15 +45,29 @@ find_program(XSLTPROC xsltproc REQUIRED) # Generate the config file for navit/navigation-core if(NOT ${YOCTO_CONFIG}) - execute_process( - OUTPUT_FILE ${NAVIT_BIN_DIR}/navit_genivi_navigationcore.xml - COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore.xsl ${navit_SOURCE_DIR}/navit/navit_shipped.xml - ) + if (WITH_PLUGIN_MIGRATION) + execute_process( + OUTPUT_FILE ${NAVIT_BIN_DIR}/navit_genivi_navigationcore.xml + COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore_capi.xsl ${navit_SOURCE_DIR}/navit/navit_shipped.xml + ) + else() + execute_process( + OUTPUT_FILE ${NAVIT_BIN_DIR}/navit_genivi_navigationcore.xml + COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore.xsl ${navit_SOURCE_DIR}/navit/navit_shipped.xml + ) + endif() else() - execute_process( - OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/navit_genivi_navigationcore.xml - COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore.xsl ${NAVIT_CMAKE_DIR}/../navit/navit_shipped.xml - ) + if (WITH_PLUGIN_MIGRATION) + execute_process( + OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/navit_genivi_navigationcore.xml + COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore_capi.xsl ${NAVIT_CMAKE_DIR}/../navit/navit_shipped.xml + ) + else() + execute_process( + OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/navit_genivi_navigationcore.xml + COMMAND ${XSLTPROC} ${CMAKE_CURRENT_SOURCE_DIR}/navit_genivi_navigationcore.xsl ${NAVIT_CMAKE_DIR}/../navit/navit_shipped.xml + ) + endif() endif() add_definitions(-DPLUGIN=1) @@ -75,12 +89,9 @@ if(${YOCTO_CONFIG}) include_directories(${STAGING_INCDIR}/navit) endif() -add_subdirectory(configuration-plugin) add_subdirectory(guidance-plugin) -add_subdirectory(locationinput-plugin) - add_subdirectory(mapmatchedposition-plugin) add_subdirectory(routing-plugin) @@ -92,5 +103,9 @@ add_subdirectory(enhancedposition-plugin) if (WITH_PLUGIN_MIGRATION) set(FRANCA_DIR "${API_DIR}/franca") add_subdirectory(configuration-server-plugin) + add_subdirectory(locationinput-server-plugin) +else() + add_subdirectory(configuration-plugin) + add_subdirectory(locationinput-plugin) endif() diff --git a/src/navigation/navigation-core/configuration-server-plugin/genivi_navigationcore_configuration.cxx b/src/navigation/navigation-core/configuration-server-plugin/genivi_navigationcore_configuration.cxx index b16a418..88c15de 100644 --- a/src/navigation/navigation-core/configuration-server-plugin/genivi_navigationcore_configuration.cxx +++ b/src/navigation/navigation-core/configuration-server-plugin/genivi_navigationcore_configuration.cxx @@ -78,50 +78,6 @@ static const map32_t country_map[] = { {"JPN","JP"}, }; -static const char * -map_3_to_2(const map32_t *map, int len, const char *in) -{ - int i; - for (i = 0 ; i < len ; i++) - if (!strcmp(map[i].c3,in)) - return map[i].c2; - return ""; -} - -static const char * -map_2_to_3(const map32_t *map, int len, const char *in) -{ - int i; - for (i = 0 ; i < len ; i++) - if (!strcmp(map[i].c2,in)) - return map[i].c3; - return ""; -} - -static const char * -language_3_to_2(const char *in) -{ - return map_3_to_2(language_map, sizeof(language_map)/sizeof(language_map[0]), in); -} - -static const char * -language_2_to_3(const char *in) -{ - return map_2_to_3(language_map, sizeof(language_map)/sizeof(language_map[0]), in); -} - -static const char * -country_3_to_2(const char *in) -{ - return map_3_to_2(country_map, sizeof(country_map)/sizeof(country_map[0]), in); -} - -static const char * -country_2_to_3(const char *in) -{ - return map_2_to_3(country_map, sizeof(country_map)/sizeof(country_map[0]), in); -} - class NavigationCoreConfigurationServerStub: public ConfigurationStubDefault { public: diff --git a/src/navigation/navigation-core/locationinput-server-plugin/CMakeLists.txt b/src/navigation/navigation-core/locationinput-server-plugin/CMakeLists.txt new file mode 100644 index 0000000..8600ed9 --- /dev/null +++ b/src/navigation/navigation-core/locationinput-server-plugin/CMakeLists.txt @@ -0,0 +1,116 @@ +########################################################################### +# @licence app begin@ +# SPDX-License-Identifier: MPL-2.0 +# +# Component Name: configuration-server-plugin +# +# Author: Philippe Colliot +# +# Copyright (C) 2015, PCA Peugeot Citroën +# +# 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@ +########################################################################### +project(locationinput-server-plugin) +cmake_minimum_required(VERSION 2.8) + +message(STATUS ${PROJECT_NAME}) + +set(CMAKE_VERBOSE_MAKEFILE on) +set(CMAKE_CXX_FLAGS "-Wall -std=c++0x") + + + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) + + +# DBus Path +if(DBUS_LIB_PATH) + message(STATUS "DBUS_LIB_PATH = " ${DBUS_LIB_PATH}) + set(DBUS_INCLUDE_DIRS ${DBUS_LIB_PATH}/include/dbus-1.0 ${DBUS_LIB_PATH}/lib/dbus-1.0/include) + set(DBUS_LIBDIR ${DBUS_LIB_PATH}/lib) + set(DBUS_LIBRARIES ${DBUS_LIB_PATH}/lib/libdbus-1.so) +else() + message(FATAL_ERROR "Please specify the path to your patched DBus library using -DDBUS_LIB_PATH=yourPath") +endif() + +# Packages +find_package(CommonAPI 3.1.5 REQUIRED) +find_package(CommonAPI-DBus 3.1.5 REQUIRED) + + +#pkg_check_modules(DBUS "dbus-1 >= 1.8.4") // #to be fixed, it doesn't work so the paths are set manually (see above) +pkg_check_modules(COMMONAPI "CommonAPI >= 3.1.5") +pkg_check_modules(COMMONAPI_DBUS "CommonAPI-DBus >= 3.1.5") +pkg_check_modules(GOBJECT gobject-2.0) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(DBUS_CPP_GLIB dbus-c++-glib-1) + + +# Add the Franca files (that will generate the CommonAPI stuff) +set(COMMONAPI_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/src-gen") +add_subdirectory(${FRANCA_DIR}/navigation/navigationcore "${CMAKE_CURRENT_BINARY_DIR}/franca") + +# Path to the generated files +set(API_VERSION_MAJOR 4) +set(API_VERSION "v${API_VERSION_MAJOR}") +set(PRJ_SRC_GEN_ROOT_PATH ${COMMONAPI_GEN_DIR}/${API_VERSION}/org/genivi) #files shared by all the APIs +set(PRJ_SRC_GEN_NAVIGATION_PATH ${PRJ_SRC_GEN_ROOT_PATH}/navigation) #files shared by the navigation APIs +set(PRJ_SRC_GEN_NAVIGATIONCORE_PATH ${PRJ_SRC_GEN_NAVIGATION_PATH}/navigationcore) #files shared by the navigationcore APIs + +# Source Files +set(FRANCA_FILE "LocationInput") +FILE(GLOB PRJ_LOCAL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cxx) +FILE(GLOB PRJ_STUB_GEN_SRCS + ${PRJ_SRC_GEN_ROOT_PATH}/*DBusStub*.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*Types.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*DBusDeployment.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*StubDefault.cpp + ${PRJ_SRC_GEN_NAVIGATION_PATH}/*DBusStub*.cpp ${PRJ_SRC_GEN_NAVIGATION_PATH}/*Types.cpp ${PRJ_SRC_GEN_NAVIGATION_PATH}/*DBusDeployment.cpp ${PRJ_SRC_GEN_NAVIGATION_PATH}/*StubDefault.cpp + ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH}/${FRANCA_FILE}DBusStub*.cpp ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH}/${FRANCA_FILE}Types.cpp ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH}/${FRANCA_FILE}DBusDeployment.cpp ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH}/${FRANCA_FILE}StubDefault.cpp + ) +FILE(GLOB PRJ_STUB_IMPL_SRCS + ${PRJ_SRC_GEN_ROOT_PATH}/*Stub*.cpp + ${PRJ_SRC_GEN_NAVIGATION_PATH}/*Stub*.cpp + ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH}/${FRANCA_FILE}Stub*.cpp + ) + +set(PRJ_SRCS ${PRJ_LOCAL_SRCS} ${PRJ_STUB_GEN_SRCS} ${PRJ_STUB_IMPL_SRCS}) + +include_directories( + ${COMMONAPI_GEN_DIR} + ${PRJ_SRC_GEN_ROOT_PATH} + ${PRJ_SRC_GEN_NAVIGATION_PATH} + ${PRJ_SRC_GEN_NAVIGATIONCORE_PATH} + ${DBUS_INCLUDE_DIRS} + ${COMMONAPI_INCLUDE_DIRS} + ${COMMONAPI_DBUS_INCLUDE_DIRS} + ${GOBJECT_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${DBUS_CPP_GLIB_INCLUDE_DIRS} +) + +link_directories( + ${DBUS_LIBDIR} + ${COMMONAPI_LIBDIR} + ${COMMONAPI_DBUS_LIBDIR} + ${GOBJECT_LIBRARY_DIRS} + ${GLIB_LIBRARY_DIRS} + ${DBUS_CPP_GLIB_DIRS} +) + +set(LIBRARIES + ${DBUS_LIBRARIES} + ${COMMONAPI_LIBRARIES} + ${COMMONAPI_DBUS_LIBRARIES} + ${GOBJECT_LIBRARIES} + ${GLIB_LIBRARIES} + ${DBUS_CPP_GLIB_LIBRARIES} +) + +# Build service +module_add_library(genivi_navigationcore_locationinput_server ${PRJ_SRCS}) +target_link_libraries(genivi_navigationcore_locationinput_server ${LIBRARIES}) + diff --git a/src/navigation/navigation-core/locationinput-server-plugin/genivi_navigationcore_locationinput.cxx b/src/navigation/navigation-core/locationinput-server-plugin/genivi_navigationcore_locationinput.cxx new file mode 100644 index 0000000..db45729 --- /dev/null +++ b/src/navigation/navigation-core/locationinput-server-plugin/genivi_navigationcore_locationinput.cxx @@ -0,0 +1,570 @@ +/** +* @licence app begin@ +* SPDX-License-Identifier: MPL-2.0 +* +* \copyright Copyright (C) 2013-2014, PCA Peugeot Citroen +* +* \file genivi_navigationcore_locationinput.cxx +* +* \brief This file is part of the Navit POC. +* +* \author Martin Schaller <martin.schaller@it-schaller.de> +* +* \version 1.0 +* +* 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: +* +* <date>, <name>, <description of change> +* +* @licence end@ +*/ +#include <dbus-c++/glib-integration.h> +#include "config.h" +#define USE_PLUGINS 1 +#include "debug.h" +#include "plugin.h" +#include "item.h" +#include "config_.h" +#include "navit.h" +#include "search.h" +#include "callback.h" +#include "event.h" +#include "coord.h" +#include "transform.h" + +#include <CommonAPI/CommonAPI.hpp> +#include <CommonTypes.hpp> +#include <NavigationTypes.hpp> +#include <NavigationCoreTypes.hpp> +#include <LocationInputStubDefault.hpp> + +#if (!DEBUG_ENABLED) +#undef dbg +#define dbg(level,...) ; +#endif + +using namespace v4::org::genivi::navigation::navigationcore; +using namespace v4::org::genivi::navigation; +using namespace v4::org::genivi; + +class LocationInputServerStub; + +class LocationInputObj +{ + public: + struct search_list *m_sl; + NavigationTypes::Handle m_handle; + NavigationTypes::Handle m_session; + LocationInput::AddressAttribute m_criterion; + uint32_t m_windowsize; + struct attr m_search; + LocationInputServerStub *mp_locationinput; + struct callback *m_callback; + struct event_idle *m_event; + bool m_spell; + bool m_spell_backspace; + std::vector< std::vector< LocationInput::Address > > m_data; + int m_chunk; + int m_count; + void SetSelectionCriterion(NavigationTypes::Handle SessionHandle, LocationInput::AddressAttribute SelectionCriterion); + void Search(NavigationTypes::Handle SessionHandle, const std::string& InputString, uint32_t MaxWindowSize); + void SelectEntry(const NavigationTypes::Handle& SessionHandle, const uint32_t& Index); + struct navit *get_navit(void); + struct mapset *get_mapset(struct navit *navit); + void IdleStop(void); + void Idle(void); + void Spell(NavigationTypes::Handle SessionHandle, const std::string& InputCharacter, uint32_t MaxWindowSize); + void RequestListUpdate(NavigationTypes::Handle sessionHandle, const uint16_t& offset, uint16_t maxWindowSize); + void GetEntry(uint16_t index, LocationInput::Address &entry); + void ValidateAddress(NavigationTypes::Handle sessionHandle, const LocationInput::Address &inputAddress); + LocationInputObj(LocationInputServerStub *locationinput, uint32_t handle); + ~LocationInputObj(); +}; + +class LocationInputServerStub : public LocationInputStubDefault { + +public: + LocationInputServerStub(){ + m_version.setVersionMajor(3); + m_version.setVersionMinor(0); + m_version.setVersionMicro(0); + m_version.setDate("21-01-2014"); + } + + ~LocationInputServerStub(){} + + /** + * description: getVersion = This method returns the API version implemented by the server + * application + */ + void getVersion(const std::shared_ptr<CommonAPI::ClientId> _client, getVersionReply_t _reply) { + _reply(m_version); + } + + /** + * description: createLocationInput = This method creates a new location input and retrieves a + * handle + */ + void createLocationInput(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, createLocationInputReply_t _reply){ + uint32_t LocationInputHandle; + dbg(lvl_debug,"enter\n"); + LocationInputHandle=1; + while (mp_handles[LocationInputHandle]) { + LocationInputHandle++; + if (LocationInputHandle == 256) + throw DBus::ErrorLimitsExceeded("Out of location handles"); + } + mp_handles[LocationInputHandle]=new LocationInputObj(this, LocationInputHandle); + _reply(LocationInputHandle); + } + + /** + * description: deleteLocationInput = This method deletes a location input and its associated + * resources + */ + void deleteLocationInput(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, deleteLocationInputReply_t _reply){ + dbg(lvl_debug,"enter\n"); + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + delete(obj); + mp_handles[_locationInputHandle]=NULL; + _reply(); + } + + /** + * description: getSupportedAddressAttributes = This method retrieves the supported address + * attributes + */ + void getSupportedAddressAttributes(const std::shared_ptr<CommonAPI::ClientId> _client, getSupportedAddressAttributesReply_t _reply){ + LocationInput::AddressAttributeList addressAttributes; + addressAttributes.resize(5); + addressAttributes[0]=LocationInput::AddressAttribute::COUNTRY; + addressAttributes[1]=LocationInput::AddressAttribute::CITY; + addressAttributes[2]=LocationInput::AddressAttribute::STREET; + addressAttributes[3]=LocationInput::AddressAttribute::HOUSENUMBER; + addressAttributes[4]=LocationInput::AddressAttribute::FULL_ADDRESS; + _reply(addressAttributes); + } + + /** + * description: setAddress = This method sets the address to start with for the LocationInput + * identified by the given handle + */ + void setAddress(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, LocationInput::Address _address, setAddressReply_t _reply){ + dbg(lvl_debug,"enter\n"); + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + throw DBus::ErrorNotSupported("Not yet supported"); + _reply(); + } + + /** + * description: setSelectionCriterion = This method sets the selection criterion for the + * current speller, search input and the corresponding result-lists for the + * current session + */ + void setSelectionCriterion(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, LocationInput::AddressAttribute _selectionCriterion, setSelectionCriterionReply_t _reply){ + dbg(lvl_debug,"enter\n"); + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->SetSelectionCriterion(_sessionHandle, _selectionCriterion); + _reply(); + } + + /** + * description: spell = This method sends the next spell input for the current session + */ + void spell(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, std::string _inputCharacter, uint16_t _maxWindowSize, spellReply_t _reply){ + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->Spell(_sessionHandle, _inputCharacter, _maxWindowSize); + _reply(); + } + + /** + * description: search = This method sends the search input for the current session + */ + void search(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, std::string _inputString, uint16_t _maxWindowSize, searchReply_t _reply){ + dbg(lvl_debug,"enter\n"); + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->Search(_sessionHandle, _inputString, _maxWindowSize); + _reply(); + } + + /** + * description: requestListUpdate = This method sends a request for more list elements for the + * current session + */ + void requestListUpdate(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, uint16_t _offset, uint16_t _maxWindowSize, requestListUpdateReply_t _reply){ + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + + obj->RequestListUpdate(_sessionHandle, _offset, _maxWindowSize); + _reply(); + } + + /** + * description: selectEntry = This method triggers selection of a result list entry by index + */ + void selectEntry(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, uint16_t _index, selectEntryReply_t _reply){ + dbg(lvl_debug,"enter\n"); + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->SelectEntry(_sessionHandle, _index); + _reply(); + } + + /** + * description: getEntry = This method synchronously gets the address for the given result list + * entry + */ + void getEntry(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, uint16_t _index, getEntryReply_t _reply){ + LocationInput::Address ret; + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->GetEntry(_index, ret); + _reply(ret); + } + + /** + * description: validateAddress = This method validates an address from different sources than + * Navigation + */ + void validateAddress(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, LocationInput::Address _inputAddress, validateAddressReply_t _reply){ + LocationInputObj *obj=mp_handles[_locationInputHandle]; + if (!obj) + throw DBus::ErrorInvalidArgs("location handle invalid"); + obj->ValidateAddress(_sessionHandle, _inputAddress); + _reply(); + } + + /** + * description: reverseGeocode = This method transforms a geocoordinate into an address + */ + void reverseGeocode(const std::shared_ptr<CommonAPI::ClientId> _client, ::v4::org::genivi::navigation::NavigationTypes::Handle _sessionHandle, ::v4::org::genivi::navigation::NavigationTypes::LocationHandle _locationInputHandle, ::v4::org::genivi::navigation::NavigationTypes::Coordinate2D _coordinate, reverseGeocodeReply_t _reply){ + throw DBus::ErrorNotSupported("Not yet supported"); + } + +private: + CommonTypes::Version m_version; + std::map<uint32_t, LocationInputObj *> mp_handles; + +}; + +struct navit * +LocationInputObj::get_navit(void) +{ + struct attr navit; + if (!config_get_attr(config, attr_navit, &navit, NULL)) + return NULL; + return navit.u.navit; +} +struct mapset * +LocationInputObj::get_mapset(struct navit *navit) +{ + struct attr mapset; + if (!navit_get_attr(navit, attr_mapset, &mapset, NULL)) + return NULL; + return mapset.u.mapset; +} + +void +LocationInputObj::SetSelectionCriterion(NavigationTypes::Handle SessionHandle, LocationInput::AddressAttribute SelectionCriterion) +{ + m_criterion=SelectionCriterion; + switch(m_criterion) { + case LocationInput::AddressAttribute::COUNTRY: + m_search.type=attr_country_name; + break; + case LocationInput::AddressAttribute::CITY: + m_search.type=attr_town_name; + break; + case LocationInput::AddressAttribute::STREET: + m_search.type=attr_street_name; + break; + case LocationInput::AddressAttribute::HOUSENUMBER: + m_search.type=attr_house_number; + break; + case LocationInput::AddressAttribute::FULL_ADDRESS: + m_search.type=attr_address; + break; + default: + throw DBus::ErrorInvalidArgs("Invalid selection criterion"); + } + g_free(m_search.u.str); + m_search.u.str=NULL; + mp_locationinput->fireCurrentSelectionCriterionEvent(m_handle, m_criterion); +} + +void +LocationInputObj::Search(NavigationTypes::Handle SessionHandle, const std::string& InputString, uint32_t MaxWindowSize) +{ + IdleStop(); + g_free(m_search.u.str); + + m_session=SessionHandle; + m_search.u.str=g_strdup(InputString.c_str()); + m_windowsize=MaxWindowSize; + m_spell=false; + + search_list_search(m_sl, &m_search, 0); + m_event=event_add_idle(0, m_callback); +} + +void +LocationInputObj::Spell(NavigationTypes::Handle SessionHandle, const std::string& InputCharacter, uint32_t MaxWindowSize) +{ + IdleStop(); + + m_spell=true; + m_spell_backspace=false; + m_session=SessionHandle; + char *newstr; + const char *input=InputCharacter.c_str(); + int len=strlen(input)+1; + dbg(lvl_debug,"input '%s' (%d)\n",input,strlen(input)); + if (m_search.u.str && strlen(m_search.u.str)) { + const char *i=input; + char c; + newstr=g_strdup(m_search.u.str); + dbg(lvl_debug,"string %s\n",newstr); + while ((c=*i++)) { + dbg(lvl_debug,"char '%c'\n",c); + if (c == '\b') { + m_spell_backspace=true; + *g_utf8_prev_char(newstr+strlen(newstr))='\0'; + } else { + int len=strlen(newstr); + newstr=g_renew(char,newstr,len+2); + newstr[len]=c; + newstr[len+1]='\0'; + } + dbg(lvl_debug,"string now %s\n",newstr); + } + } else { + if (strcmp(input,"\b")) + newstr=g_strdup(input); + else + newstr=NULL; + } + g_free(m_search.u.str); + dbg(lvl_debug,"search string '%s' (%d)\n",newstr,strlen(newstr)); + m_search.u.str=newstr; + m_windowsize=MaxWindowSize; + + search_list_search(m_sl, &m_search, 1); + dbg(lvl_debug,"backspace %d\n",m_spell_backspace); + m_event=event_add_idle(0, m_callback); + +} + +void +LocationInputObj::RequestListUpdate(NavigationTypes::Handle sessionHandle, const uint16_t& offset, uint16_t maxWindowSize) +{ + //for the time being, maxWindowSize is not used, the size is set during the Spell or the Search + //note that it gets all the results in one shot (to be improved!), per bunch of maxWindowSize data + //not really what is specified.. + //offset is supposed to be n*maxWindowSize in that case + + if (m_windowsize > 0) + { + int i = offset/m_windowsize; + int shift = offset%m_windowsize; + uint16_t window=m_data[i].size(); + mp_locationinput->fireSearchResultListEvent(m_handle, m_count, (offset-shift), window, m_data[i]); + } +} + +void +LocationInputObj::SelectEntry(const NavigationTypes::Handle &SessionHandle, const uint32_t& Index) +{ + LocationInput::Address *res=NULL; + std::vector<LocationInput::AddressAttribute> next; + std::size_t window=0; + bool guidable=false; + for (std::size_t i = 0 ; i < m_data.size() ; i++) { + if (Index >= window && Index < window+m_data[i].size()) { + res=&m_data[i][Index-window]; + break; + } + window+=m_data[i].size(); + } + if (!res) + throw DBus::ErrorInvalidArgs("Invalid index"); + search_list_select(m_sl, m_search.type, Index+1, 1); + switch(m_criterion) { + case LocationInput::AddressAttribute::COUNTRY: + next.push_back(LocationInput::AddressAttribute::COUNTRY); + next.push_back(LocationInput::AddressAttribute::CITY); + break; + case LocationInput::AddressAttribute::CITY: + next.push_back(LocationInput::AddressAttribute::COUNTRY); + next.push_back(LocationInput::AddressAttribute::CITY); + next.push_back(LocationInput::AddressAttribute::STREET); + break; + case LocationInput::AddressAttribute::STREET: + case LocationInput::AddressAttribute::HOUSENUMBER: + next.push_back(LocationInput::AddressAttribute::COUNTRY); + next.push_back(LocationInput::AddressAttribute::CITY); + next.push_back(LocationInput::AddressAttribute::STREET); + next.push_back(LocationInput::AddressAttribute::HOUSENUMBER); + break; + } + if (res->find(LocationInput::AddressAttribute::LATITUDE) != res->end()) + guidable=true; + mp_locationinput->fireContentUpdatedEvent(m_handle, guidable, next, *res); +} + +void +LocationInputObj::IdleStop(void) +{ + if (m_event) { + event_remove_idle(m_event); + m_event=NULL; + } +} + +void +LocationInputObj::Idle(void) +{ + dbg(lvl_debug,"enter\n"); + mp_locationinput->fireSearchStatusEvent(m_handle, LocationInput::SearchStatus::SEARCHING); + struct search_list_result *res; + int chunk=0; + uint16_t count=0; + m_data.resize(0); + m_data.resize(1); + while ((res=search_list_get_result(m_sl))) { + LocationInput::Address entry; + if (res->country && res->country->name) { + dbg(lvl_debug,"country %s\n",res->country->name); + entry[LocationInput::AddressAttribute::COUNTRY] = std::string(res->country->name); + } + if (res->town && res->town->common.town_name) { + dbg(lvl_debug,"town %s\n",res->town->common.town_name); + entry[LocationInput::AddressAttribute::CITY] = std::string(res->town->common.town_name); + } + if (res->street && res->street->name) { + dbg(lvl_debug,"street %s\n",res->street->name); + entry[LocationInput::AddressAttribute::STREET] = std::string(res->street->name); + } + if (res->house_number && res->house_number->house_number) { + dbg(lvl_debug,"house number %s\n",res->house_number->house_number); + entry[LocationInput::AddressAttribute::HOUSENUMBER] = std::string(res->house_number->house_number); + } + if (res->c) { + struct coord_geo g; + struct coord c; + c.x=res->c->x; + c.y=res->c->y; + transform_to_geo(res->c->pro, &c, &g); + entry[LocationInput::AddressAttribute::LATITUDE] = g.lat; + entry[LocationInput::AddressAttribute::LONGITUDE] = g.lng; + } + m_data[chunk].push_back(entry); + if (m_data[chunk].size() >= m_windowsize) { + chunk++; + m_data.resize(chunk+1); + } + count++; + } + + // the search_list_get_unique has been removed from the svn in the r5549, so navit needs to be patched for upper versions + if (m_spell) { + char *unique; + if (m_spell_backspace) + unique=g_strdup(m_search.u.str); + else + unique=search_list_get_unique(m_sl, NULL); + m_spell_backspace=false; + if (unique) { + g_free(m_search.u.str); + m_search.u.str=unique; + char *next=search_list_get_unique(m_sl, unique); + if (next) { + mp_locationinput->fireSpellResultEvent(m_handle, unique, next, false); + g_free(next); + } + } + else + mp_locationinput->fireSpellResultEvent(m_handle, "", "\b", false); + } + + m_count = count; //amount of data + m_chunk = chunk; //amount of lists of data + + mp_locationinput->fireSearchStatusEvent(m_handle, LocationInput::SearchStatus::FINISHED); + IdleStop(); + +} + +static void +LocationInputObj_Idle(LocationInputObj *obj) +{ + obj->Idle(); +} + +void +LocationInputObj::GetEntry(uint16_t index, LocationInput::Address &entry) +{ +} + +void +LocationInputObj::ValidateAddress(NavigationTypes::Handle sessionHandle, const LocationInput::Address &inputAddress) +{ +} + +LocationInputObj::LocationInputObj(LocationInputServerStub *locationinput, uint32_t handle) +{ + mp_locationinput=locationinput; + m_handle=handle; + m_sl=search_list_new(get_mapset(get_navit())); + m_count=0; + m_chunk=0; + m_search.type=attr_none; + m_search.u.str=NULL; + m_event=NULL; + m_callback=callback_new_1(reinterpret_cast<void (*)(void)>(LocationInputObj_Idle), this); +} + +LocationInputObj::~LocationInputObj() +{ + IdleStop(); + callback_destroy(m_callback); + g_free(m_search.u.str); + search_list_destroy(m_sl); +} + +void +plugin_init(void) +{ + // Common API data init + std::shared_ptr < CommonAPI::Runtime > runtime = CommonAPI::Runtime::get(); + + const std::string &domain = "local"; + const std::string &instance = "LocationInput"; + + std::shared_ptr<LocationInputServerStub> myServiceLocationInput = std::make_shared<LocationInputServerStub>(); + + bool successfullyRegistered = runtime->registerService(domain, instance, myServiceLocationInput); + while (!successfullyRegistered) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + successfullyRegistered = runtime->registerService(domain, instance, myServiceLocationInput); + } +} diff --git a/src/navigation/navigation-core/navit_genivi_navigationcore_capi.xsl b/src/navigation/navigation-core/navit_genivi_navigationcore_capi.xsl new file mode 100644 index 0000000..74cc2bc --- /dev/null +++ b/src/navigation/navigation-core/navit_genivi_navigationcore_capi.xsl @@ -0,0 +1,63 @@ +<?xml version="1.0"?> +<!-- ************************************************************************ +* Component Name: Navit POC +* Author: Martin Schaller <martin.schaller@it-schaller.de> +* +* Copyright (C) 2012, GENIVI Alliance, Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +************************************************************************ --> +<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xsl:template match="/config/plugins/plugin[1]" priority="1" > + <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/configuration-server-plugin/.libs/libgenivi_navigationcore_configuration_server.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/locationinput-server-plugin/.libs/libgenivi_navigationcore_locationinput_server.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/routing-plugin/.libs/libgenivi_navigationcore_routing.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/session-plugin/.libs/libgenivi_navigationcore_session.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/guidance-plugin/.libs/libgenivi_navigationcore_guidance.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/mapmatchedposition-plugin/.libs/libgenivi_navigationcore_mapmatchedposition.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../navigation-core/enhancedposition-plugin/.libs/libgenivi_positioning_enhancedposition.so" ondemand="no"/> + <xsl:text>
 </xsl:text> + <plugin path="../../poi-cam/.libs/libgenivi_poiservice_cam_navit.so" ondemand="no"/> + </xsl:template> + <xsl:template match="/config/plugins/plugin"> + <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="/config/navit"> + <xsl:copy><xsl:attribute name="flags">3</xsl:attribute><xsl:apply-templates select="@*|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="/config/navit/graphics"> + <xsl:copy><xsl:attribute name="enabled">no</xsl:attribute><xsl:apply-templates select="@*|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="/config/navit/gui"> + <xsl:copy><xsl:attribute name="enabled">no</xsl:attribute><xsl:apply-templates select="@*[not(name()='enabled')]|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="/config/navit/vehicle[@name='Local GPS']"> + <xsl:copy><xsl:attribute name="enabled">no</xsl:attribute><xsl:apply-templates select="@*[not(name()='enabled')]|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="/config/navit/vehicle[@name='Demo']"> + <vehicle name="EnhancedPosition" profilename="car" active="yes" source="enhancedposition://"/> + <xsl:text>
 </xsl:text> + <xsl:copy><xsl:attribute name="active">no</xsl:attribute><xsl:apply-templates select="@*[not(name()='enabled' or name()='active')]|node()"/></xsl:copy> + </xsl:template> + <xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template> +</xsl:transform> diff --git a/test/navigation/test-location-input-capi.py b/test/navigation/test-location-input-capi.py new file mode 100755 index 0000000..5f2f9fc --- /dev/null +++ b/test/navigation/test-location-input-capi.py @@ -0,0 +1,485 @@ +#!/usr/bin/python +# -*- coding: latin-1 -*- + +""" +************************************************************************** +* @licence app begin@ +* SPDX-License-Identifier: MPL-2.0 +* +* @copyright Copyright (C) 2014, Alpine Electronics R&D Europe GmbH +* +* @file test-location-input.py +* +* @brief This simple test shows how the location input +* could be easily tested using a python script +* +* @author Stephan Wiehr <stephan.wiehr@alpine.de> +* @author Philippe Colliot <philippe.colliot@mpsa.com> +* +* @version 1.1 +* +* 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/. +* List of changes: +* 04-02-2016, Philippe Colliot, Update to the new API ('i' for enumerations and 'yv' for variants), add status handler +* +* @licence end@ +************************************************************************** +""" + +import dbus +import gobject +import dbus.mainloop.glib +from xml.dom.minidom import parse +import xml.dom.minidom +import argparse +import sys +import errno +#import pdb;pdb.set_trace() + + +# constants as defined in the Navigation API +LATITUDE = 0x00a0 +LONGITUDE = 0x00a1 +ALTITUDE = 0x00a2 +FULL_ADDRESS = 0x00b2 +COUNTRY = 0x00a6 +STATE = 0x00a7 +CITY = 0x00a8 +ZIPCODE = 0x00a9 +STREET = 0x00aa +HOUSE_NUMBER = 0x00ab +CROSSING = 0x00ac +DISTRICT = 0x00ad +PHONE_NUMBER = 0x00ae +POI_NAME = 0x00af +TOWN_CENTER = 0x00b0 +FINISHED = 0x00c2 + +# List of addresses +COUNTRY_STRING = list() +CITY_STRING = list() +STREET_STRING = list() +HOUSE_NUMBER_STRING = list() + +# Default size of the list +WINDOW_SIZE = 20 + +# Search mode (0 = Spell, 1 = Full string search) +country_search_mode = 1 +city_search_mode = 0 +street_search_mode = 1 #set to full because of a bug to be fixed in the plug-in +house_number_search_mode = 1 + +print '\n--------------------------\n' + \ + 'LocationInput Test' + \ + '\n--------------------------\n' + +parser = argparse.ArgumentParser(description='Location input Test for navigation PoC and FSA.') +parser.add_argument('-l','--loc',action='store', dest='locations', help='List of locations in xml format') +parser.add_argument("-v", "--verbose", action='store_true',help='print the whole log messages') +args = parser.parse_args() + +if args.locations == None: + print('location file is missing') + sys.exit(1) +else: + try: + DOMTree = xml.dom.minidom.parse(args.locations) + except OSError as e: + if e.errno == errno.ENOENT: + print('file not exists') + sys.exit(1) + location_set = DOMTree.documentElement + +print("Area : %s" % location_set.getAttribute("area")) + +locations = location_set.getElementsByTagName("location") + +for location in location_set.getElementsByTagName("location"): + COUNTRY_STRING.append(location.getElementsByTagName("country")[0].childNodes[0].data) + CITY_STRING.append(location.getElementsByTagName("city")[0].childNodes[0].data) + STREET_STRING.append(location.getElementsByTagName("street")[0].childNodes[0].data) + #HOUSE_NUMBER_STRING.append(location.getElementsByTagName("number")[0].childNodes[0].data) + HOUSE_NUMBER_STRING.append('') #there's a bug in the navigation core when the house number doesn't exist, so deactivated + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +# connect to session bus +bus = dbus.SessionBus() + +def vprint(text): + if args.verbose: + print(text) + +# Turn selection criteria values to their corresponding string description +def selection_criterion_to_string(selection_criterion): + return_value = '' + if selection_criterion == LATITUDE: + return_value += 'Latitude' + elif selection_criterion == LONGITUDE: + return_value += 'Longitude' + elif selection_criterion == COUNTRY: + return_value += 'Country' + elif selection_criterion == STATE: + return_value += 'State' + elif selection_criterion == CITY: + return_value += 'City' + elif selection_criterion == TOWN_CENTER: + return_value += 'City center' + elif selection_criterion == ZIPCODE: + return_value += 'ZipCode' + elif selection_criterion == STREET: + return_value += 'Street' + elif selection_criterion == HOUSE_NUMBER: + return_value += 'House number' + elif selection_criterion == CROSSING: + return_value += 'Crossing' + elif selection_criterion == FULL_ADDRESS: + return_value += 'Full address' + else: + return_value += str(selection_criterion) + + return return_value + + +# Prepare a dictionary array for pretty printing + +def dictionary_array_to_string(dict_array, linefeed, offset=0): + return_value = '' + i = offset + for item in dict_array: + return_value += str(i) + '. ' + unicode(dictionary_to_string(item)) + if i < offset + len(dict_array) - 1: + return_value += linefeed + i += 1 + + return return_value + + +# Prepare a dictionary for pretty printing +# NB: the value is supposed to be [UInt8, Variant], according to the DBus '(yv)', used by CommonAPI +def dictionary_to_string(dictionary): + return_value = '' + i = 0 + for key in dictionary.keys(): + value = dictionary[key][1] + return_value += selection_criterion_to_string(key) + ' = ' + unicode(value) + i += 1 + if i < len(dictionary): + return_value += ', ' + + return return_value + + +# Prepare a selection criteria array for pretty printing + +def selection_criteria_array_to_string(selection_criterion_array): + return_value = '' + i = 0 + for item in selection_criterion_array: + return_value += selection_criterion_to_string(item) + i += 1 + if i < len(selection_criterion_array): + return_value += ', ' + + return return_value + + +def print_current_context(): + vprint('\tACTIVE CONTEXT: selection criterion = ' + selection_criterion_to_string(current_selection_criterion) + \ + ', search string = \'' + entered_search_string + '\'') + + +def change_selection_criterion(selection_criterion): + global current_selection_criterion + + current_selection_criterion = selection_criterion + location_input_interface.setSelectionCriterion(dbus.UInt32(session_handle), dbus.UInt32(location_input_handle), + dbus.Int32(current_selection_criterion)) + + +# Spell search +def spell_search(handle, entered_string, search_string, valid_characters, first=0): + global entered_search_string + + vprint('-> SpellSearch - entered \'' + entered_string + '\' target \'' + search_string + '\'') + + if unicode(search_string) != unicode(entered_string): + found = unicode(search_string).lower().find(unicode(entered_string).lower()) + if found == 0: + is_valid = -1 + if first == 0: + spell_character = search_string[len(entered_string)] + is_valid = valid_characters.find(spell_character) + else: + spell_character='' + is_valid = 0 + if is_valid != -1: + entered_search_string = entered_string + spell_character + vprint('\nACTION: Spell search, selection criterion = ' + \ + selection_criterion_to_string(current_selection_criterion) + ', trying \'' + spell_character + \ + '\'') + location_input_interface.spell(dbus.UInt32(session_handle), dbus.UInt32(handle), + dbus.String(spell_character), dbus.UInt16(20)) + else: + print 'TEST FAILED (Target character can not be entered)' + loop.quit() + else: + print 'TEST FAILED (Unexpected completion)' + loop.quit() + else: + print 'Full spell match' + + +# Full string search +def full_string_search(handle, search_string): + global entered_search_string + global found_exact_match + + entered_search_string = search_string + found_exact_match = 1 # Force exact match for full string search + vprint('\nACTION: Full string search, selection criterion = ' + \ + selection_criterion_to_string(current_selection_criterion) + ', trying \'' + search_string + '\'') + location_input_interface.search(dbus.UInt32(session_handle), dbus.UInt32(handle), dbus.String(search_string), + dbus.UInt16(20)) + + +def evaluate_address(address, guidable): + test_passed = 0 + print '\nAddress complete!\nEvaluating...' + if COUNTRY_STRING[current_address_index] == '': + test_passed = 1 + elif address[COUNTRY][1] == COUNTRY_STRING[current_address_index]: + print 'Country\t\t\t-> ok (' + address[COUNTRY][1] + ')' + if CITY_STRING[current_address_index] == '': + test_passed = 1 + elif address[CITY][1] == CITY_STRING[current_address_index]: + print 'City\t\t\t-> ok (' + address[CITY][1] + ')' + if STREET_STRING[current_address_index] == '': + test_passed = 1 + elif address[STREET][1] == STREET_STRING[current_address_index]: + print 'Street\t\t\t-> ok (' + address[STREET][1] + ')' + if HOUSE_NUMBER_STRING[current_address_index] == '': + test_passed = 1 + elif address[HOUSE_NUMBER][1] == HOUSE_NUMBER_STRING[current_address_index]: + print 'House number\t-> ok (' + address[HOUSE_NUMBER][1] + ')' + test_passed = 1 + + if guidable == 1: + if test_passed == 1: + print 'TEST PASSED' + else: + print 'TEST FAILED (wrong address)' + loop.quit() + else: + print 'TEST FAILED (non-guidable address)' + loop.quit() + address_index = current_address_index + 1 + if address_index < len(COUNTRY_STRING): + startSearch(address_index) + else: + print 'END OF THE TEST' + loop.quit() + + +# Signal receiver + +# Handler for ContentUpdated callback + +def search_status_handler(handle,status): + vprint('\n::Search status ' + str(int(status))) + if status == FINISHED: + location_input_interface.requestListUpdate(dbus.UInt32(session_handle), dbus.UInt32(handle), + dbus.UInt16(0), + dbus.UInt16(WINDOW_SIZE)) + + +def content_updated_handler(handle, guidable, available_selection_criteria, address): + global target_search_string + global entered_search_string + + vprint('\n::ContentUpdated for LocationInputHandle ' + str(int(handle))) + print_current_context() + vprint('\tGuidable = ' + str(guidable)) + vprint('\tAvailable selection criteria = ' + selection_criteria_array_to_string(available_selection_criteria)) + vprint('\tADDRESS: '+dictionary_to_string(address)) + + search_mode = -1 + + if current_selection_criterion == COUNTRY: + change_selection_criterion(CITY) + target_search_string = CITY_STRING[current_address_index] + search_mode = city_search_mode + elif current_selection_criterion == CITY: + change_selection_criterion(STREET) + target_search_string = STREET_STRING[current_address_index] + search_mode = street_search_mode + elif current_selection_criterion == STREET: + change_selection_criterion(HOUSE_NUMBER) + target_search_string = HOUSE_NUMBER_STRING[current_address_index] + search_mode = house_number_search_mode + elif current_selection_criterion == HOUSE_NUMBER: + target_search_string = '' + + entered_search_string = '' + + if target_search_string == '': + evaluate_address(address, guidable) + elif search_mode == 0: + spell_search(handle, entered_search_string, target_search_string, '', 1) + elif search_mode == 1: + full_string_search(handle, target_search_string) + else: + print '\nTEST FAILED (Invalid search mode)' + loop.quit() + +# Handler for SpellResult callback +def spell_result_handler(handle, unique_string, valid_characters, full_match): + global entered_search_string + global spell_next_character + global found_exact_match + global available_characters + + vprint('\n::SpellResult for LocationInputHandle '+str(int(handle))) + if unique_string != entered_search_string: + vprint('\tAUTOCOMPLETE: \'' + entered_search_string + '\' -> \'' + unique_string + '\'') + entered_search_string = unique_string + available_characters = valid_characters + print_current_context() + vprint('\tUnique string = \''+unique_string+'\'') + vprint('\tValid Characters = \''+valid_characters+'\'') + vprint('\tFull Match = '+str(full_match)) + + if len(valid_characters) == 1: + if unicode(valid_characters[0]) == u'\x08': + print '\nTEST FAILED (Dead end spelling)' + loop.quit() + + if unicode(entered_search_string) == unicode(target_search_string): + found_exact_match = 1 + + spell_next_character = 1 + + +# Handler for SearchResultList callback + +def search_result_list_handler(handle, total_size, window_offset, window_size, result_list_window): + global spell_next_character + global found_exact_match + + vprint('\n::SearchResultList for LocationInputHandle ' + str(int(handle))) + print_current_context() + vprint('\tTotal size = ' + str(int(total_size)) + ', Window offset = ' + str(int(window_offset)) + \ + ', Window size = ' + str(int(window_size))) + vprint('\t' + dictionary_array_to_string(result_list_window, '\n\t', window_offset)) + + if found_exact_match == 1: + found_exact_match = 0 + i = 0 + for address in result_list_window: + if unicode(address[current_selection_criterion][1]) == target_search_string: + vprint('\nACTION: Found exact match, selecting \''+unicode(address[current_selection_criterion][1]) + \ + '\' (Session '+str(int(session_handle)) + ' LocationInputHandle ' + str(int(handle))+')') + location_input_interface.selectEntry(dbus.UInt32(session_handle), dbus.UInt32(handle), dbus.UInt16(i)) + break + i += 1 + if i == window_size: + vprint('\nACTION: Found exact match, searching in next page (Session '+str(int(session_handle)) +\ + ' LocationInputHandle ' + str(int(handle))+')') + location_input_interface.requestListUpdate(dbus.UInt32(session_handle), dbus.UInt32(handle), + dbus.UInt16(window_offset + window_size), + dbus.UInt16(window_size)) + elif total_size == 1: + selection_name = result_list_window[0][current_selection_criterion] + if selection_name[1] == target_search_string: + vprint('\nACTION: Single entry list, selecting \'' + selection_name[1] + \ + '\' (Session '+str(int(session_handle)) + ' LocationInputHandle ' + str(int(handle))+')') + location_input_interface.selectEntry(dbus.UInt32(session_handle), dbus.UInt32(handle), dbus.UInt16(0)) + else: + print '\nTEST FAILED (Unexpected single result list)' + loop.quit() + elif spell_next_character == 1: + spell_next_character = 0 + spell_search(handle, entered_search_string, target_search_string, available_characters) + + +# add signal receiver +bus.add_signal_receiver(search_status_handler, + dbus_interface='org.genivi.navigation.navigationcore.LocationInput', + signal_name='searchStatus') + +bus.add_signal_receiver(search_result_list_handler, + dbus_interface='org.genivi.navigation.navigationcore.LocationInput', + signal_name='searchResultList') + +bus.add_signal_receiver(spell_result_handler, + dbus_interface='org.genivi.navigation.navigationcore.LocationInput', + signal_name='spellResult') + +bus.add_signal_receiver(content_updated_handler, + dbus_interface='org.genivi.navigation.navigationcore.LocationInput', + signal_name='contentUpdated') + + +# Timeout +def timeout(): + print 'Timeout Expired' + print '\nTEST FAILED\n' + loop.quit() + +def startSearch(address_index): + global entered_search_string + global spell_next_character + global found_exact_match + global available_characters + global target_search_string + global country_search_mode + global current_address_index + current_address_index = address_index + entered_search_string = '' + spell_next_character = 0 + found_exact_match = 0 + available_characters = '' + target_search_string = COUNTRY_STRING[current_address_index] + + change_selection_criterion(COUNTRY) + if country_search_mode == 0: + spell_search(location_input_handle, entered_search_string, target_search_string, available_characters, 1) + elif country_search_mode == 1: + full_string_search(location_input_handle, target_search_string) + + +session = bus.get_object('org.genivi.navigationcore.Session', '/org/genivi/navigationcore') +session_interface = dbus.Interface(session, dbus_interface='org.genivi.navigationcore.Session') + +# Get SessionHandle +session_handle = session_interface.CreateSession(dbus.String('test location input')) +print 'Session handle = ' + str(session_handle) + +location_input_obj = bus.get_object('org.genivi.navigation.navigationcore.LocationInput_LocationInput', '/LocationInput') +location_input_interface = dbus.Interface(location_input_obj, dbus_interface='org.genivi.navigation.navigationcore.LocationInput') +# Get LocationInputHandle +location_input_handle = location_input_interface.createLocationInput(dbus.UInt32(session_handle)) +print 'LocationInput handle = ' + str(location_input_handle) + +attributes = location_input_interface.getSupportedAddressAttributes() +print 'Initially supported address attributes = ' + selection_criteria_array_to_string(attributes) + +# Configuration +current_address_index = 0 +entered_search_string = '' +spell_next_character = 0 +found_exact_match = 0 +available_characters = '' +target_search_string = '' +current_selection_criterion = 0 + +startSearch(0) + +# Main loop +gobject.timeout_add(10000, timeout) +loop = gobject.MainLoop() +loop.run() |