Search by Tags

C / C++ Developer Workflow on Windows

 
Applicable for

Article updated at 31 Mar 2020
Subscribe for this article updates

Introduction

Using the Torizon Visual Studio Development Tools Extension and Visual Studio 2019 it is easy to setup a highly productive developer workflow for creating Torizon based apps. To demonstrate this, we will:

  • Create a weatherboard application using InfluxDB and Grafana.
  • Write a docker-compose file to create the InfluxDB and Grafana container images.
  • Use the extension to build the container images that host our application code.

Ultimately, we will deploy our application to a Toradex device running TorizonCore, set breakpoints in our source and step through it as you'd expect to be able to do developing a modern application.

The main goal is to present, through one example, how you can develop applications for your own use case.

This article complies to the Typographic Conventions for Torizon Documentation.

Prerequisites

Brief Background

There are many weather APIs available, our sample uses the OpenWeatherMap’s current weather and 5 day forecast APIs.

Current weather is displayed in Grafana using the singlestat widget and the forecast is displayed using graphs.

The current weather is fetched twice every minute and the forecast is fetched only once on application start. The Forecast API provides datapoints at 3hr intervals. Forecast graphs are available for Temperature, Humidity and Pressure at the moment, although the API provides access to much more data.

The Openweather API key is referred to as appid in the requests.

Setting up the Source Code

  • Clone the Torizon samples repository to your PC:
$ git clone https://github.com/toradex/torizon-samples.git
  • Create a new project using Visual Studio 2019.
    • Select Torizon C/C++ Aplication as the project template.
    • Name your project WeatherSample.
    • Select a location for the files, be sure to check the box Place solution and project in the same directory and then click Create.
    • On the next dialog, choose arm64v8, arm32v7 or both, depending on the module you wish to target.
  • Using the Windows File Explorer:
    • Copy get-owm.cpp, weather.cpp and the include folder from the Torizon Samples repo you cloned earlier (they are located in the weather/src folder) to the root of your new project location.
  • Back in Visual Studio 2019:
    • Click Project > Add Existing Item, then add both get-owm.cpp and weather.cpp.
      • Additionally, add the header files from the include folder.
    • Delete main.cpp from Solution Explorer (you can choose Delete, not just Remove).
    • Rename weather.cpp to main.cpp.

You'll need to update the API key in the demo code. This value is currently hardcoded and needs to be replaced at the following functions:

  • getowmforecast.setApiKey();
  • getowmcurrent.setApiKey();

You can also modify the geographic coordinates you want to receive the data by modifying the functions:

  • getowmforecast.setCity();
  • getowmcurrent.setCity();

Setting up the InfluxDB API

In this example, we will also be building InfluxDB API code as part of our project. You can get that code from Github with the following command:

git clone https://github.com/awegrzyn/influxdb-cxx

Of course, you could clone this repo directly into your project. However, in a real project, you'll likely be committing your own code to a git repo, and so you would clone this code to a folder outside of your project. At this point, let's create a folder in your WeatherSample project folder and name it influxdb-cxx. Then you'll need to copy the src and include folders from the InfluxDB API project into this new influxdb-cxx folder.

As before, you'll need to do Project > Add Existing Item back in Visual Studio to add the contents of the influxdb-cxx\src and influxdb-cxx\include folders.

Setting the Project Properties

With the WeatherSample project selected on Solution Explorer, click Project > Properties to edit the project level properties. We need to include our header files, so you can start by expanding Configuration Properties > C/C++ > General, then edit the Additional Include Directories to include our include folder. You'll also need to include the include folder we added from the InfluxDB API which is located at influxdb-cxx\include.

Next we will change the C++ language to v17 by expanding Configuration Properties > C/C++ > Language, and changing the C++ Language Standard to C++17 (-std=c++17). This specific C++ version is required for libraries in this demonstration only.

Next, we need to include a few libraries for use by our app. To do so, expand Configuration Properties > Linker > Input and add the following value for Library Dependencies:

curl;pthread;boost_system;jsoncpp

With these settings made click on the Apply button and Ok button to close the Property Pages window.

Setting the Torizon Application Properties

The Torizon Visual Studio Development Tools Extension creates a new property window in any Torizon C/C++ Aplication project. To open that window, click Project > WeatherSample > Properties... item and select the Torizon C/C++ Aplication node. Be sure that All Configurations and All Platforms are selected at the top of the Property Pages window.

Now drop down the value next to Configuration in the main panel, and click <Properties...>. This window allows you to configure the values that are ultimately passed to Docker to manage various aspects of the containers that will be built as part of the project. At the top, the Username should be set to the default (torizon) and the Configuration should be Common.

We need a few developer packages to be installed inside the container running on our development machine that will build the ARM application. To set those up, choose your target architecture from the tabs below, then in Visual Studio click the Edit... button on the devpackages row. Now add the following packages listed below to devpackages row.

libcurl4-openssl-dev:armhf libboost1.67-dev:armhf libboost-system1.67-dev:armhf libboost-test1.67-dev:armhf libboost-program-options1.67-dev:armhf libjsoncpp-dev:armhf
libcurl4-openssl-dev:arm64 libboost1.67-dev:arm64 libboost-system1.67-dev:arm64 libboost-test1.67-dev:arm64 libboost-program-options1.67-dev:arm64 libjsoncpp-dev:arm64

We also need a few extra packages to be included with our application. Click the Edit... button on the extrapackages row, and add these:

libcurl4 libboost-system1.67.0 libjsoncpp1

For our demo project, we need a network connection between our containers. To add/edit the values in the bottom section of the property window, simply click the ... button, then click New in the popup, and enter the value on the new row. For our example, add the following new value for the Networks: setting in the property window:

#%application.id%#_backend

One final step we need to complete in the Torizon Application Properties window is to set up a docker-compose file. Click the "..." button next to Docker-compose script: and save it with the filename: docker-compose.yml.

docker-compose.yml

Multi-container: Docker Compose

In the previous step, we created a setting to instruct our project to look for a docker-compose file, now we need to create that file. In the toolbar at the top of Solution Explorer, toggle the button to Show All Files if it is not already enabled. You will now see a folder in Solution Explorer named appconfig_0. Expand that folder and open the docker-compose.yml file.

It is a strong suggestion when using Docker to have only one process running in each container, since containers are very light weight we don't care as much about multiple containers. For our application, we'll need a total of 3 containers. The first is for our application code, the Torizon Visual Studio Development Tools Extension will manage that one. In addition, we need a second container for Grafana and a third one for InfluxDB. We'll set those up in our docker-compose.yml file.

We'll also create the networks and volumes we need, link the containers, and expose Grafana on port 3000.

version: '2.4'
services:
    grafana:
        container_name: grafana
        depends_on:
            - influxdb
        networks:
            - backend
            - frontend
        volumes:
            - 'grafana-storage:/var/lib/grafana'
        ports:
            - '3000:3000'
        links:
            - influxdb
        image: grafana/grafana

    influxdb:
        container_name: influxdb
        networks:
            - backend
        volumes:
            - 'influxdb-grafana:/var/lib/influxdb'
        image: influxdb

networks:
  backend:
    internal: true
  frontend:   
    internal: false

volumes:
  grafana-storage:
  influxdb-grafana:

Build and Deploy

Now we're ready to build and deploy our application. Open main.cpp and set a breakpoint on the first line inside the main() function call:

main.cpp
GetOWM getowmcurrent;

Now, click the Deploy and Debug Torizon Application button in the Torizon Toolbar. It will take a few minutes for all the steps to complete. When the local container is created and configured, it will compile the application. Then it will deploy the containers to the target device. Finally, the code will execute and will pause at the breakpoint. Click continue and allow the code to run.

A Connection Error

One of the first things our sample code does is to create the InfluxDB database. However, it's possible that this line of code runs before InfluxDB is actually up and running. By default, the sample code performs 45 retries, 1 second apart, waiting for the DB to be available. If this is not long enough, you can change the value: int retries = 45;

Configuring Grafana

With the application up and running, you can now point your browser to http://X.X.X.X:3000, where X.X.X.X is the IP Address of the target device. Login with the default credentials (user: admin, password: admin).

Setup data source

  • Click add data source
  • Select InfluxDB as a data source type
  • Set URL to http://influxdb:8086 under HTTP (we're using a docker link, so we can access the InfluxDBcontainer by the container name we set up in our docker-compose file.)
  • Under InfluxDB Details, set the Database to "Weather", the database name we created in code.
  • Finally, set Min time interval to 3h. The forecast API provides data points at 3h intervals. If this value is set to anything under 3h, the forecast graphs will show as dots instead of connected lines/curves.
  • Now, click the Save & Test button, it should say "Data source is working."

Import Weather Dashboard

  • Go to the Dashboards menu and select Manage.
  • Click Import then Upload and browse for the Weather-<timestamp>.json file from the weather sample directory. (You can also choose to paste the JSON.)
  • Finally, under Options, enter Weather in the Name field and click import. The Dashboard is now ready.

Next Steps / Additional Resources

Additional Torizon Resources