The C++ Connector gives you the opportunity to access the OKAPI software from within your own C++ code. We provide you with a connector that includes all essential functions to communicate with the authentication at Auth0 and the calculation server at OKAPI. You can use it as a template for your own code, compile it as a library or embed the code in your software. The complete code is available on Github and will be updated there in the future. For this tutorial we will use CMake to build the code, but you can of course use it with any build-system you are comfortable with. The connector itself is on purpose kept very simple to keep the business logic on the side of your program. It basically only takes over the REST communication.
The following tutorial is divided in two parts:
- Setup of the code with an explanation of the general routine of the communication
- Step-by-step example of your first calculation
We recommend strongly to read through this page once to ensure that you do not miss any important information.
What is needed?
The connector (and this tutorial) are kept very concise. To be able to run it, you will need the following:
- a C++ compiler: e.g. gcc or clang
- CMake: we used verison 3.2
- a text editor or IDE of your choice
- a terminal
- libraries: boost_system, boost_thread, boost_chrono, crypto, ssl and cpprest
So far, we tested the tutorial and connector on Ubuntu 18.04 and macOS 10.14.
Getting and compiling the code
To get the code, simply download it from Github. Inside the repository, you will find a readme, the license file, a CMakeLists file and a src folder, which contains the source folder and another CMakeLists file. To compile the library, create a new build
directory and change into it. Then, run the following two commands:
cmake ../
make install
With the first command, cmake configures your build environment and looks for your compilers etc., the second one takes over the actual compilation. This will give you a shared object (.so) in in the lib folder, which contains all the functions needed to communicate with OKAPI. You can now go ahead and use the library.
Setting up your own code
Now, you probably want to use the library in your own code. For this, we first add a short description how it generally works. The complete connector is made off three routines: Init, SendRequest and GetResult. The routine basically do what their name says: Use the first one to log in to our server (or more correctly: receive a token to gain access), with the second one you can place requests for execution, and with the third you can retrieve the results from the server.
Most probably, you have your software ready and some idea of how you want to include the connector. Therefore, we will not focus on this here, but rather take the fast road. The first thing you need is a main
routine from which you can call the connector. For this, create a tutorial.cpp
file in the source folder. In here, you can write a little program to send a request to OKAPI and retreive the results. To be able to compile it correctly, you need to add the new executable to the cmake file in the src folder:
set(Casablanca_LIBRARIES "-lboost_system -lboost_thread -lboost_chrono -lcrypto -lssl -lcpprest")
# Build the neptune executable based on the given source files
add_library(cpp-connector SHARED okapiConnector.cpp)
# Build the executable based on the given source files
add_executable(tutorial tutorial.cpp)
# link all the libraries needed
target_link_libraries(tutorial cpp-connector ${Casablanca_LIBRARIES})
# Install the libraries into the lib directory and executrables to bin
install(TARGETS cpp-connector tutorial
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib)
After writing your code (see below), run the following two commands from the build folder, as described above:
cmake ../
make install
To finally run the executable, run LD_LIBRARY_PATH ../lib ./tutorial
.
As announced, find below an example for a small code which runs a pass prediction using OKAPI. For all possible services and requests, please refer to the API-Documentation. Note that we are currently introducing a “generic” API, which allows more flexible data types, which will be the standard in the future. Before compiling it, make sure to add your username and password to the code below.
#include "OkapiConnector.h"
#include "OkapiConnector.h"
// Tutorial to send service execution request and get result
int main() {
// initializing communication
OkapiConnector okapi;
// USER INPUT SECTION
// authentication
string username = "sign";
string password = "up";
// url to OKAPI server
std::string baseUrl = "http://okapi.ddns.net:34569";
// user input PASS PREDICTION
double altitude = 0.048;
double longitude = 10.645;
double latitude = 52.328;
std::string start = "2018-08-07T19:01:00.000Z";
std::string end = "2018-08-07T19:04:00.000Z";
std::string tlePassPrediction = "1 25544U 98067A 18218.76369510 .00001449 00000-0 29472-4 0 9993\n2 25544 51.6423 126.6422 0005481 33.3092 62.9075 15.53806849126382";
// ACTUAL WORK
// Auth0 authentication
OkapiConnector::completeResult okapiResult = okapi.init(methods::POST,username,password);
// some user information
std::cout << "Authentication completed" << std::endl;
std::cout << okapi.accessToken << std::endl;
// Prepare the JSON for pass prediction
web::json::value simpleGroundLocation;
simpleGroundLocation[U("altitude")] = web::json::value::number(altitude);
simpleGroundLocation[U("longitude")] = web::json::value::number(longitude);
simpleGroundLocation[U("latitude")] = web::json::value::number(latitude);
web::json::value timeWindow;
timeWindow[U("start")] = web::json::value::string(start);
timeWindow[U("end")] = web::json::value::string(end);
web::json::value passPredRequestBody;
passPredRequestBody[U("simple_ground_location")] = simpleGroundLocation;
passPredRequestBody[U("time_window")] = timeWindow;
passPredRequestBody[U("tle")] = web::json::value::string(tlePassPrediction);
// prepare urls etc. to send the request
std::string overviewUrl = "/pass/prediction/requests";
std::string overviewEndpoint = baseUrl + overviewUrl;
http_client okapiRequest(overviewEndpoint);
http_request requestOverview(methods::POST);
requestOverview.set_body(passPredRequestBody);
requestOverview.headers().add(U("access_token"), okapi.accessToken);
// send the request
okapiResult = okapi.sendRequest(okapiRequest, requestOverview);
std::string requestIdOverview = okapi.requestId;
// get results for overview creation and print them in the terminal
std::string overviewUrlGet = "/pass/predictions/";
std::string overviewGetEndpoint = baseUrl + overviewUrlGet + requestIdOverview;
http_client okapiGetOverview(overviewGetEndpoint);
http_request getOverview(methods::GET);
getOverview.headers().add(U("access_token"), okapi.accessToken);
okapiResult = okapi.getResult(okapiGetOverview, getOverview);
while (okapiResult.error.code == 202) {
okapiResult = okapi.getResult(okapiGetOverview, getOverview);
std::cout << "Your request is not ready yet. The request was successful." << std::endl;
sleep(1);
}
std::string resultsOverview = okapiResult.body.serialize();
std::cout << resultsOverview << std::endl;
return 0;
}