Programming

We've shown you some clients which consume OwnTracks data, but you may well wish to dip your fingers into programming something of your own. Creating a program to consume OwnTracks data isn't particularly difficult, and we're going to show you what you can do with a bit of Python together with the Paho Python client.

Getting started: Paho Python

We're assuming you have Python installed, which you can verify by attempting to invoke python -V; if installed, it tells you the version number. We're also assuming you have pip installed (a Python package manager) which may be called pip2 or something on your machine. You may have to install setuptools via your distribution's package manager.

Install the Paho Python module using

pip install paho-mqtt

Progress reports

Assume we want to create a program which should report the location of our friends, as a simple list:

TID = n4 is currently at 51.0343863, 9.4763712
TID = n7 is currently at 52.7343671, 7.8764431
TID = jp is currently at 53.134404655, 8.1063173

We need a small utility program which will subscribe to location publishes received by your broker by connecting to it on localhost and subscribing to owntracks/+/+ (a wild-card expression in which each + means anything at this level).

The Code

For each received message, the utility attempts to decode the JSON payload and then prints the tracker-ID (TID) as well as latitude, longitude coordinates. Keep a copy of our OwnTracks-JSON documentation handy and study the topic names of each possible publish by the apps.

#!/usr/bin/env python

import paho.mqtt.client as mqtt
import json

# The callback for when the client successfully connects to the broker
def on_connect(client, userdata, rc):
    ''' We subscribe on_connect() so that if we lose the connection
        and reconnect, subscriptions will be renewed. '''

    client.subscribe("owntracks/+/+")

# The callback for when a PUBLISH message is received from the broker
def on_message(client, userdata, msg):

    topic = msg.topic

    try:
        data = json.loads(str(msg.payload))

        print "TID = {0} is currently at {1}, {2}".format(data['tid'], data['lat'], data['lon'])
    except:
        print "Cannot decode data on topic {0}".format(topic)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)

# Blocking call which processes all network traffic and dispatches
# callbacks (see on_*() above). It also handles reconnecting.

client.loop_forever()

Micro Map

Assume for a moment that you alter the program above in such a way as that it writes your current location in JSON format to a file called me.json which could look like this:

{
    "lat": 48.858334,
    "lon" : 2.295134,
    "tid":"JJ"
}

We could then create a Web page which would load that JSON and display a marker on a map.

micro map

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Micromap</title>
    <meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0" />

    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <style type="text/css">
      body {  font-size: 80%; }

      td { border-bottom: 1px solid; border-right: 1px dotted;}

      #map-canvas { height: 100% }

    </style>
     <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
     <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
     <script src="http://code.jquery.com/jquery-migrate-1.1.1.min.js"></script>
    <script src="functions.js"></script>
  </head>
  <body>
    <div>
      <div id="map-canvas" style='width: 100%; height: 400px;'/></div>
    </div>
  </body>
</html>

functions.js

function initialize() {
    var json = (function () {
        var json = null; 
        $.ajax({ 
            'type' : 'GET',
            'async': false, 
            'cache' : false,
            'global': true, 
            'url'   : 'me.json',  // URI of JSON file we create
            'dataType': "json", 
            'success': function (data) {
                json = data;
                return json;
             }
        });
    return json;
    })();

    var data = json;
    console.log(JSON.stringify(data));

    var center = new google.maps.LatLng(data.lat, data.lon);
    mapOptions = {
        center: center,
        zoom: 12,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false,
        disableDefaultUI: false,
        panControl: false,
        scaleControl: false,
        streetViewControl: false,
        overviewMapControl: false,
    };

    map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

    var LatLng = new google.maps.LatLng(data.lat, data.lon); 
    var m = new google.maps.Marker({
        position: LatLng,
        map: map,
        title: data.tid,
    });
}
google.maps.event.addDomListener(window, 'load', initialize);

would result in a map being displayed in your Web browser with a marker at the last location received by your MQTT broker. Note: the marker won't move; we leave that as an exercise to you, or just head over and look at some clients which do that for you.

Testing

Testing location-based apps is a bit of a, well, pain, but remember there are a few simple tricks you can apply:

  • Use the publish now button in OwnTracks to fire a location update. The smart phone won't really move much of course, but it'll allow you to test your program a bit.
  • Publish your own OwnTracks-JSON payload to the broker with mosquitto_pub or similar.

Last words

Consuming OwnTracks messages from your MQTT broker isn't particularly difficult, and people have built nice programs doing so.