First Steps
The Remote Interface is a set of commands that lets you interact with the fleet / truck navigator software. It provides over 40 functions in 5 categories, like getting GPS-information, adding stations, setting system properties or starting a navigation. These functions are described in detail on the following pages. To get started with the interface take a look at the First Steps and the Tutorials page. They contain guides from basic to advanced topics. For further information, we also have some demos on the Demos page.
Basics
The remote interface communicates with the client via window messages, so you should be familiar with these. The navigation software acts as a server and your application is a client who "talks" to this server. You can send and receive messages to and from the navigator and there is the possibility to exchange data between the applications (the data will be transfered over shared memory).
What you need
- A basic knowledge of window messages
- A PTV navigator with the remote interface dll (ri.dll)
- A development environment (eVC4 / Visual Studio).
What you can do
- Change Application options (like the speaker volume)
- Geocode and inverse geocode addresses and coordinates
- Control the program flow (like starting a navigation)
- Handle stations (includes adding and removing of stations)
- Get GPS information
Including the remote interface
To use the interface, be sure to place your application in the same directory as the navigator application and the ri.dll or copy the ri.dll to a proper place where all applications can access it (like SYSTEMROOT on Windows) otherwise your program and the navigator cannot communicate with each other. Then, add the following to your code:
#define USE_LOADLIBRARY #include "TNSRemoteInterfaceDll.h"
The USE_LOADLIBRARY
define causes the dll to be loaded automatically, no other steps will be needed to start.
What are commands
Throughout the help, we use the term command for the process of sending the navigator information and getting information from the navigator. Because of the message based system of the interface, it's not a function or a method like in other interfaces, but a combination of a message and optional data which will belong to this message. These messages are standard Windows Messages which will be handled in a message loop and therefore the interface is not synchronous. Be sure to have this in mind when sending commands to the navigator ! Every command has a distinct message to send, and some have optional functions to read or write the data. You will find an overview and further explanation of all commands in the API-Reference.
Sending and receiving commands
First, be sure that the navigator software is running and you are at least in the main menu (see picture below) of the navigator.
The procedure of sending commands and receiving the acknowledgement answer is always the same:
You send a message to the interface (e.g. RI_MESSAGE_SYSTEMINFO
to get some system information). To know if the request succeeded, check in your WindowProc()-procedure for the same message you sent (the navigator will sent this message back after executing the request). When the message arrives, the wParam of WindowProc() will be RI_NOERROR on success or an error value if the request failed.
Attention
It is essential to check the acknowledgement message in the WindowProc to know if the command succeeded.
The messages you can send are described in the Commands-Description (see API-Reference).
Before sending a message to the remote interface, you have to take care that the interface is active and loaded. This is done by the method RI_GetTNS() which returns a window-handle to the interface.
In the Tutorials, you will find this code to check for the interface:
if ( !IsWindow( RI_GetTNS() ) ) return RI_NAVIGATIONNOTACTIVE;
With this handle, you can use the PostMessage() method to send the message to the interface:
PostMessage( RI_GetTNS(), request, WPARAM(h_client), id );
Each message sent must have a unique identifier, see parameter 'id' in the above example.
For the tutorials and for general use, we wrote two little convenience functions:
- RI_MESSAGE which will check for the handle and send the message, so you don't have to do it for yourself, and
-
GetUniqueID which will create the appropriate id.
Both methods are used in the tutorials.
Types of commands
There are two types of RI-commands:
- Commands without data-transfer (like setting the day/night mode)
- Commands with data-transfer (like adding a station).
Commands without data-transfer are the simplest way to communicate with the interface. Just use the above mentioned RI_MESSAGE
function to send the request to the navigator, check in WindowProc()
if the message succeeded (the navigator will always send a message back to your app to signalize the proper processing of the request and for error handling) and your done.
Commands with data-transfer can send and receive data from the interface. For this purpose, every command with data-transfer capability has it's own functions to read and write the data. As an example, the read-function for the SearchAddress-Command is called RI_SearchAddress_ReadData(), the write-function is called RI_SearchAddress_WriteData(). The data for the transfer is stored in a struct, in the SearchAddress example it's called RI_CSearchAddress. (See the API-Reference for details).
To send data, first fill the struct with the appropriate content, then write the data to the interface and at last, send the command:
RI_CSearchAddress data; wcscpy(data.m_address, L"D,76131,Karlsruhe,Stumpfstrasse,1"); LPARAM id = GetUniqueID(); LRESULT sharing_ret = RI_SearchAddress_WriteData( id, data ); if ( RI_MESSAGE( RI_MESSAGE_SEARCHADDRESS, GetSafeHwnd(), id ) == RI_NOERROR ) { }
Again, you have to create a unique id. This time, you must use the same id for writing the data and sending the message (the id is needed to relate the data to the message).
To receive data, check in wndproc for your message and read the data with the reader-function:
if ( message == RI_MESSAGE_SEARCHADDRESS ) { if ( (LRESULT)wParam == RI_NOERROR ) { RI_CSearchAddress data; LRESULT read_suc = RI_SearchAddress_ReadData( lParam, data ); } }
Restrictions when sending commands
Attention
Avoid mixing remote interface calls with user interaction, this can result in undefined behaviour.
A problem that sometimes occurs is that the client sends a remote command and the user of the navigation software presses a button (e.g. sending a station will automatically switch to the stationlist dialog, and some users press the "calculate" button while the navigator is adding some other station). To avoid these situations the best way is to disable the user interface by the client before sending such commands and enable it afterwards. If the client doesn't block the user interaction, the remote interface will autoblock it for certain commands.
These commands are:
- StartNavigation: Start a navigation
- StartNavigationOverBCR: Start a navigation from a BCR File
- StartSimulation: Start a simulation
- RoutePlanning: Calc a route and retrieve route information
In these routines, the remote interface will disable user interaction with the navigator before executing the call and enable it after the call, if there was no explicit BlockUserInteraction-command sent by the client. This will not help in situations like adding multiple stations to the navigator. In this case, if you don't block the interface, we block it, but we can do this only an a command basis, so the result would be: block interface -> add station -> unblock -> block -> addstation -> unblock and so on. This is most time not what you expect and doesn't avoid all user interaction.
Attention
We recommend to explicitly block the user interface always by calling BlockUserInteraction before sending commands where the user may have interaction possibilities.
Calling BlockUserInteraction will disable the internal block/allow mechanism.