Real-time bicycle tracking map using PubNub

Introduction

Bicycle tracker utilizes the LinkIt ONE development board's GNSS features to acquire the position of a bike in real time. The data is then uploaded to the EON real-time dashboard over a GPRS connection using the PubNub LinkIt ONE library support. The EON real-time dashboard provides a visualization of the data on a map.

By the end of this tutorial you'll have a fully functioning IoT prototype, which gathers GPS data, then transmits the data through a GPRS connection to enable control and visualization using cloud services on a PC.

This tutorial guides you through:

  • Building the prototype, with details of the hardware requirements and how to put them together to create the Bike Tracker.
  • Creating the software to provide the interfaces with the GNSS receiver on the LinkIt ONE development board to collect the data and implement data communications to send that data to the EON dashboard.
  • Creating publish and subscribe channels using the PubNub API and PubNub LinkIt ONE library to communicate the data with the PubNub Data Stream Network, using the GPRS features of the LinkIt ONE development board.
  • Sending your Bike Tracker location data to the EON real-time dashboard for real-time visualization.

At the end of the tutorial there are details on where to go for additional information on the LinkIt ONE development board and how to create software for it.

Before you start

If you haven't built a LinkIt ONE project before, this section describes the steps you need to follow before commencing this project.

The project requires user accounts for PubNub and Mapbox.

Install the development software

Full details on downloading and installing the Arduino IDE and LinkIt ONE SDK then configuring the IDE and upgrading the board firmware are provided in the LinkIt ONE quick start guide. Complete this before you continue if you haven't already set up your development environment.

Building the Bike Tracker hardware

This section describes the hardware and electronics needed to build Bike Tracker and provides details on how to put them together.

What you need

To build the Bike Tracker hardware, in addition to a LinkIt ONE development board, you need the following components:

ComponentDescriptionSource
AntennasGPS + GLONASS antenna.
GSM Antenna
LinkIt ONE Development Kit
SIM card2G data plan enabled micro-SIM card 
CableMicro-USB cable 
PowerPolymer Li-ion 1000mAh batteryLinkIt ONE Development Kit

Putting the components together

This section provides step-by-step instructions on putting the Bike Tracker hardware together.

Step 1 — Antennas

Attach the GPS+GLONASS and GSM antennas to their corresponding pins on the LinkIt ONE development board as follows:

Connecting the antennas

Step 2 — SIM card

Insert the SIM card supporting GSM/GPRS communication with a network provider operating in the 850/900/1800/1900 MHz frequency range and classified as Class 12, as shown below.

SIM card slot on the LinkIt ONE development board

Step 3 — Power source

The power source in this tutorial is a polymer lithium-ion battery, one is included in the LinkIt ONE development board kit. Attach the battery source to the Li-Battery (3.7~4.2V) socket, as shown in the figure below.

The Bike Tracker complete hardware setup

Create your Bike Tracker's software

Your Bike Tracker needs an Arduino Sketch to share data from an onboard GNSS receiver. This section describes the software required as follows:

  • Overview of the Arduino sketch.
  • Creating a new PubNub app.
  • Configuring your device and its GPRS settings.
  • Styling your own map on Mapbox.
  • Overview of the JavaScript code to output data on Mapbox maps using the EON real-time dashboard and PubNub library support.

PubNub LinkIt ONE development cycle

To create PubNub apps for data streaming, you should first register for a PubNub account. The Bike Tracker tutorial follows the general steps for application development with PubNub, which you can follow in the PubNub Quick Start Guide.

Create a new PubNub App for the Bike Tracker

A PubNub app serves as an interface between your device and the network. Once you've registered your PubNub account a default project is created, as shown below.

PubNub App with Publish and Subscribe keys

The Publish Key and Subscribe Key define the app and will be used in your Arduino sketch to communicate the data from the board to the PubNub Data Stream Network.

Overview of the Arduino sketch

To create the device that will track your bike and pass the data to PubNub, an Arduino sketch is implemented, verified and uploaded to the LinkIt ONE development board. The source code is provided in a GitHub repository.

The content of a sketch is as follows:

  • Definitions of header files.
  • Definitions of variables.
  • setup() function that initializes resources, such as the GPRS module.
  • loop() function that continuously listens to and processes events from hardware and software modules such as those for GPS and GPRS. The loop() function runs forever — until the device is shutdown.

Start your Arduino project

Before you can write the code for your sketch you need to create it, which is achieved as follows:

  1. Open Arduino IDE and by default a new sketch is created and displayed.
  2. Create a folder named BikeTracker in your documents folder and on the File menu click Save As navigate to the selected folder, name the sketch BikeTracker.ino and save it.

Bike Tracker project in Arduino IDE

Add the header files for the supporting libraries

The first part of you code adds the libraries required to the BikeTracker.ino Arduino sketch.

GNSS and GPRS features libraries

The libraries that provide GNSS and GPRS support are part of LinkIt ONE API and are added as follows:

//import all the necessary files for GPRS connectivity
#include "LGPRS\LGPRS.h"
#include "LGPRS\LGPRSClient.h"
#include <LGPS\LGPS.h>

More details about these libraries can be found in the LinkIt ONE API guide.

Serial Peripheral Interface (SPI) communication

The SPI communication header file, from the Arduino SPI library. 

#include <SPI.h>

PubNub LinkIt ONE library

The real-time streaming of GPS data is implemented with PubNub LinkIt ONE library support using GPRS connectivity. The library, along with a GPRS connectivity and data transfer example, is provided in the PubNub LinkIt ONE library GitHub repository. In this project the library is used to transfer the parsed location data to PubNub.

From the PubNub LinkIt ONE library, add the PubNub.h and PubNub.cpp files to the same directory as your BikeTracker.ino project. And modify the content of the PubNub.hheader file so it includes the LGPRS library support for GPRS communication, as shown below.

#define PubNub_GPRS

#elif defined(PubNub_GPRS)
#include "LGPRSClient.h"
#define PubNub_BASE_CLIENT LGPRSClient
#else
#error PubNub_BASE_CLIENT set to an invalid value!
#endif

Then include the library header in your project. 

#include "PubNub.h"

Custom libraries

Next you add two custom libraries that offer features to parse the GPS latitude and longitude data to an appropriate String format to pass the PubNub. These are the GPSWaypoint and GPSFunctions classes originally developed for, and are described in detail in the Car Tracker tutorial.

#include "GPSWaypoint.h"
#include "GPS_functions.h"

Define the variables

Next the static variables used in the sketch are defined.

  1. ledPin to match the GPIO pin 13 to alert the user, by blinking the on board LED, whenever there is a publish or subscribe event triggered. 

    #define ledPin 13
  2.  PubNub publish and subscribe keys. These keys are associated with your PubNub app created earlier, see Create a new PubNub App for the Bike Tracker.

    char pubkey[] = "demo"; // provide the pubkey associated with your PubNub account.
    char subkey[] = "demo";// provide the subkey associated with your PubNub account.
    char channel[] = "bike-map";

Initiate the setup() function

Now the setup() function can be defined, to start the various services that will be used by the sketch.

  1. Initiate Serial communication with a baud rate of 9600 and print a message "Serial setup" to the serial output.

    void setup()
    {
        Serial.begin(9600);
        Serial.println("Serial setup");
  2. Establish communication over GPRS in a while loop, by calling the attachGPRS method of the LGPRS class. Replace the three parameters of the attachGPRS() method with your network provider's information for the access point name, username and password. Allow one second of waiting time before reconnecting to GPRS in the while loop by calling the delay(1000) function. Once it's connected, send the "LGPRS setup" message to the serial output.

      //Connect to the GRPS network in order to send/receive PubNub messages
        Serial.println("Attach to GPRS network with correct APN settings from your mobile network provider");
          //attachGPRS(const char *apn, const char *username, const char *password);
      while (!LGPRS.attachGPRS("everywhere", "eesecure", "secure"))
        {
            Serial.println(" . ");
            delay(1000);
        } 
      Serial.println("LGPRS setup");


  3.  Begin communication with PubNub using the publish (pubkey) and subscribe (subkey) keys defined earlier.

      PubNub.begin(pubkey, subkey);
        Serial.println("PubNub setup");
    }
  4. Start GPS signal reception by calling the powerOn() method of the LGPS class.

    LGPS.powerOn();

Add the loop() function

The loop() function is executed continuously providing formatted GPS coordinates such as latitude and longitude and communication with PubNub. The function call hierarchy is provided in the figure below:

loop() function's call hierarchy

  1. Acquire GPS data.

    The GPS data is acquired and formatted using the custom build functions described in the Car Tracker tutorial. 

        Serial.println("Getting GPS Data");
        //Aquire GPS position
        char GPS_formatted[] = "GPS fixed";
        gpsPosition = new GPSWaypoint();
        gpsSentenceInfoStruct gpsDataStruct;
        getGPSData(gpsDataStruct, GPS_formatted, gpsPosition);
        Serial.println(" GPS Data aquired");
  2. Create a data string upload_GPS as a combination of latitude and longitude to upload the location information to PubNub. 

    char* buffer_latitude = new char[30];
        sprintf(buffer_latitude, "%2.6f", gpsPosition->latitude);
        char* buffer_longitude = new char[30];
        sprintf(buffer_longitude, "%2.6f", gpsPosition->longitude);
    String upload_GPS = "[{\"latlng\":[" + String(buffer_latitude) + "," + String(buffer_longitude)+ "], \"data\":\"hello1\"}]"; 
        const char* upload_char = upload_GPS.c_str();
  3. Provide continuous communication to PubNub by:

    1. Publishing a message over the GPRS connection.

      Define a client object of LGPRSClient class and printout a message "publishing a message" to the serial output. The client object is then assigned to the PubNub published message. 

      LGPRSClient *client;
      Serial.println("publishing a message");
      client = PubNub.publish(channel, upload_char, 60);

      If the GPRS client is not available printout the "publishing error" message to the serial output, then wait for a second (1000 ms) by calling the delay(1000) function before trying to connect again.

      if (!client) {
          Serial.println("publishing error");
          delay(1000);
          return;
      }
    2. Call the connected() method of client object in a while loop, read the message and print it out to the serial output. 

      while (client->connected()) {
          while (client->connected() && !client->available()); // wait
          char c = client->read();
          Serial.print(c);
      }

    3. Stop the publication of messages on PubNub over the GPRS connection by calling the stop() method of the client object, then blink the LED as a confirmation with the flash(true) function. 

          client->stop();
          Serial.println();
          flash(true);

This complete the code needed in your sketch.

Run your application

With the code complete, you can now upload the sketch to your board. Once this is completed, you can monitor the serial output in Arduino and will see something similar to the following:

Serial output content of the Bike Tracker example sketch


You can also view the published messages on the PubNub App Debug console.

  1. In the Quick Links menu of your PubNub app, click Debug Console.
    Debug Console in the Quick Links menu
  2. Specify the ChannelPublish Key and Subscribe Key information
    Channel, Publish Key and Subscribe Key in the PubNub Debug Console
  3. Click Subscribe and you'll see the data communication in the messages console, as shown below.
    GPS position data on the PubNub messages consoleCongratulations, you now have a device that tracks your bike by publishing GPS data using LinkIt ONE GPRS support for the PubNub LinkIt ONE Library.

Creating your Bike Tracker Map

For the tracker to be a practical tool you will want to display the GPS data on a map. An option for doing this is Mapbox.

To start you will need to create a Mapbox account. Once this is done, the Bike Tracker tutorial follows the general steps of application development on the Mapbox.

Create a new Mapbox project for the Bike Tracker

The Mapbox project enables you to styling your map, using a style provided by Mapbox or a custom one you create. For this project use one of the styles provided by Mapbox.

  1. Click New Project to create your map.
    A new project on Mapbox
  2. Select a style for the map.
    Specifying the map style
  3. Navigate to Project from the top menu, then Settings to name your project.
    Name your project in the Settings tab
  4. Click Save to save your changes.

 

Obtaining your project's API access token and a Map ID

Each Mapbox project is identified by an API access token and a Map ID, which you can find in your project details:

Two project identifiers on Mapbox

These identifiers will be used to specify the Mapbox map and display the GPS location gathered from the Bike Tracker on the EON dashboard.

EON real-time dashboard mapping

The location data acquired by the LinkIt ONE development board and communicated to the PubNub Global Data Stream Network can now be visualized using your Mapbox map from the data on the EON real-time dashboard. To achieve this you need some JavaScript code to establish the data communication and connectivity with the data published on PubNub.

The detailed description of the EON maps and examples could be found at the EON Maps GitHub Repository.

To create your bike tracking map:

  1. Clone the EON Maps GitHub Repository to your local file system.
  2. Navigate to examples folder located in the eon-map folder of the cloned repository.
  3. Create and save an HTML file in the examples folder.
  4. Add the content for the CSS and JavaScript supporting files from Mapbox (mapbox.cssand mapbox.js) and PubNub (pubnub.min.js and pubnub-mapbox.js) as follows: 

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset=utf-8 />
        <title>EON Maps</title>
        <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
        <style>
          body {
            margin: 0;
            padding: 0;
          }
          #map {
            position:absolute;
            top:0;
            bottom:0;
            width:100%;
          }
        </style>
    
        <link href="../lib/mapbox.css" rel="stylesheet" />
        <script src="../lib/mapbox.js"></script>
    
        <script src="../bower_components/pubnub/web/pubnub.min.js"></script>
        <script src="../pubnub-mapbox.js"></script>
    
      </head>
      <body>
        <div id='map'></div>
    
             <script>
  5. Provide the subscribe key of your PubNub account and define the data communication channel for the Bike Tracker. The channel name should match the one defined in the Arduino Sketch, see Define the variables

    var pubnub = PUBNUB({ subscribe_key: 'demo', ssl: true });
    var channel = 'bike-map';
  6. Define the EON map function. Provide the name of your project (id), API access token(mb_token) and map ID (mb_id) matching your Bike Tracker map created in Mapbox, see Create a new Mapbox project for the Bike Tracker 

    eon.map({
    pubnub: pubnub,
    id: 'map',
    mb_token: 'mapbox api token',
    mb_id: 'mapbox map id,
    channel: channel,
  7. Add formatting to the map and provide a personalized icon URL for the bike. 

    options: {
              zoomAnimation: false,
            },
            marker: function (latlng, data) {
    
                var marker = new L.Marker(latlng, {
                    icon: L.icon({
                        iconUrl: 'https://d30y9cdsu7xlg0.cloudfront.net/png/15274-200.png',
                        iconSize: [24, 24]
                    })
                });
    
                var popup = '';
                if (data) {
                    popup = 'Courier ' + data + '';
                }
                else {
                    var popup = 'No data available';
                }
    
                marker.bindPopup(popup);
    
                return marker;
            }
          });
    
               var point = {
              latlng: [37.370375, -97.756138]
          };  
    
        </script>
      </body>
    </html>
  8. Open the saved HTML file in your browser and enjoy the real-time tracking of your bike ride.

Conclusion

In this tutorial you have implemented a real-time bike tracker mapping application using the LinkIt ONE development board, PubNub Global Data Stream NetworkMapbox maps,EON real-time dashboard and Arduino programming environment.

For more information on MediaTek LinkIt ONE development and prototyping board refer to LinkIt ONE developer's guide. For more information on the PubNub LinkIt ONE library refer to here.