Btraced, Raspberry Pi, Node.js, MQTT to build your own GPS tracking system

Btraced-2

The Btraced app is a great tool, especially because it allows you to upload the GPS data to your own server. Once you’ve got this aspect covered, the things you can do with the GPS data is unlimited – you can do whatever you want with it!
Personally, I’m not that interested in the ‘trip’ functionality of Btraced; I’d rather use the app to allow me to do positioning: constantly letting my Domotica system know where I am. And not just my location, soon other family members will be added as well.

Although uploading the GPS data to your own server is very convenient, accomplishing this might sound scary to some people, cause “I’ve never done that”, “don’t know how”, “don’t have a server”, “too difficult”. This post will show you that it’s none of those..

During the last few days I’ve been playing with a Raspberry Pi, Node.js and a webpage on my web server. The situation before I started with this, was that I had an ASP.Net web form on my IIS web server; this page was used for uploading the Btrace GPS data to my server and storing it in my SQL Server. After a few days I started wondering why I stored all this GPS information in a database – all I did with it was SELECT-ing the newest record and display my last-known location. What a waste of disk space..

So I added MQTT publishing to the ASP.Net page and let the SQL stuff the way it was. A few days later I completely removed the SQL stuff, and realized that using an ASP.Net page on my IIS was a bit overkill for what I was doing. There must be an easier way! And there is: I’ll show you how to create your own Btraced-upload-server without a big web server and minimal cost.

Hardware

All you need is a Raspberry Pi (model B, the one with Ethernet interface) and a LAN cable to connect it to your router or LAN. I prefer to run my Raspberry’s without keyboard, video & mouse so you’ll need a way to connect to the RPi over the LAN – my favorite tool for that is Putty. Connect your RPi to the network, power it up and find out with which IP address the RPi is using.

Network

Your gateway to Internet (modem, router, firewall) should be able to do port forwarding, cause we’ll have to forward the Btraced data to the RPi. Choose a port (e.g. 8000, 8080, 8081 but preferably not 80 cause maybe you want to run a website on your RPi one day…) and forward that port to the RPi. In the Btraced App, you’ll have to change the setting for the upload server, like this: http://ww.xx.yy.zz:pppp (assuming ww.xx.yy.zz is your external IP address and pppp is the port number).

Software

You’ll need to install Node.js and an additional Node module: xml2js. Optional: mqtt. And some extra code, which will be provided below. Just follow one of those excellent guides on ‘How to install Node.js’ that can be found on the web. Also install npm, the Node Package Manager, just to make life easier. Not comfortable with using an editor on Linux? Install an Node.js and a FTP server on your PC, edit the files on your PC, test & debug them there, install an FTP client on the RPi and ‘ftp get’ the files to your RPi once the scripts are finished.

Some code

The Btraced app uploads the data as xml over http. “Oops, so I need a http server and work with XML?” Yes you do, but it only takes 75 lines of code, so don’t be scared! Keep on reading.. here’s the code that can ‘receive’ and parse the uploaded Btraced XML data:

http = require('http');
mqtt = require('mqtt');
var parseString = require('xml2js').parseString;
var ydate = '';
var position = {};

mqttClient = mqtt.createClient(process.env.DDMC_BROKER_PORT, process.env.DDMC_BROKER_HOST, {clientId: 'Btraced', keepalive: 30000});

function processPoint(p){
  if(p.date > ydate){
    ydate = p.date;
    position.date = parseFloat(p.date);
    position.latitude = parseFloat(p.lat);
    position.longitude = parseFloat(p.lon);

    position.speed = parseFloat(p.speed);
    if(position.speed > 0){
      position.speed = Math.round(position.speed * 36)/10;
    } else {
      position.speed = 0;
    }

    if(p.course.substring(0,1) == "-"){
      position.angle = 0;
    } else {
      position.angle = parseFloat(p.course);
    }
    position.batt = Math.round(parseFloat(p.bat)*100);
  }
  return parseInt(p.id);
}

http.createServer(function (req, res) {
  if(req.method == 'POST') {
    var body='';
    var travelid = '';
    var ids=[];

    req.on('data', function (data) {
      body +=data;
    });

    req.on('end',function(){
      // explicitArray false for NOT getting all nodes as arrays
      parseString(body, {explicitArray:false}, function (err, result) {
        bwiredtravel = result.bwiredtravel;
        username = bwiredtravel.username;
        travelid = parseInt(bwiredtravel.travel.id);
        ydate = '';
        position = {};
        position.username = username;
        var points = bwiredtravel.travel.point;
        if(typeof points.length === 'undefined')
        {
          ids.push(processPoint(points));
        } else {
          for(var i=0;i<points.length;i++){
            ids.push(processPoint(points[i]));
          };
        }
        console.log(JSON.stringify(position));
        mqttClient.publish('raw/'+username+'/location/gps', JSON.stringify(position));
      });
      body = '';

      response = {};
      response.id = 0;
      response.tripid = travelid;
      response.points = ids;
      response.valid = true;

      console.log(JSON.stringify(response));
      res.end(JSON.stringify(response));
    });
  }
}).listen(8000);

That’s it? Yep.. and all that needs to be done to get this code running is entering ‘node btraced’ @ the command prompt and it’s running… If you didn’t install the mqtt module mentioned earlier then just delete all the lines containing the string ‘mqtt’ and the script will keep on working, but now the information will only be displayed on the console and not published anymore – you’ll have to find yourself another way to get the information there where you want it.

With MQTT it’s very easy to create a web page that displays the information in text and also draws a map, all real-time.  I added some reverse geocoding to complement the information with an address, et voila:

Btraced-1

I haven’t tried it, but it cannot be hard to run the web page shown above on a RPi as well.

So there you have it: your own, private, fully customizable GPS tracking system for the price of a Raspberry Pi!

Tagged , , . Bookmark the permalink.

17 Responses to Btraced, Raspberry Pi, Node.js, MQTT to build your own GPS tracking system

  1. OWK says:

    Not comfortable with Linux promt: I use winscp (http://winscp.net) on my Windows PC

    Regards
    OWK

  2. Chris says:

    Could you publish the reverse geocoding code snippet as we’ll ? ( ASP ? )

    • Reverse geocoding (and some geofencing) is done in a separate Node app:

      var geo = require('geo');
      var LatLon = require('./latlong.js');
      var tools = require('./tools');
      util = require('util');

      tools.initProcess('geocoder');

      var home = new LatLon(52.0071670, 6.0393751);

      // connect to MQTT broker.
      function connect() {
      tools.clog('connecting...');
      tools.mqttClient.connect({clientId: tools.driverId});
      };

      tools.mqttClient.on('connect', function(packet) {
      tools.mqttClient.subscribe('raw/+/location/gps');

      tools.mqttClient.on('message',function(packet){
      var person = packet.topic.split("/")[1];
      var gpsCoords = JSON.parse(packet.payload);
      processGPSData(person, gpsCoords);
      });
      });

      function processGPSData(person, coords){
      var address;
      var sensor = false;
      var txt = coords;
      var llcoords = new LatLon(coords.latitude, coords.longitude);
      var dist = home.distanceTo(llcoords, 4);
      txt +=', dst='+dist.toString()+' km';
      txt +=', in='+dist< =4?1:0).toString(); geo.geocoder(geo.google, coords , sensor, function(formattedAddress, latitude, longitude, details) { tools.mqttClient.publish('/value/'+person+'/location/gps', JSON.stringify(coords), true); tools.mqttClient.publish('/value/'+person+'/location/address', formattedAddress, true); }); } connect();

      You'll need the Node geo module. Installing with npm didn't work for me, so it's better to use the version at https://github.com/feliperazeek/geonode.
      The "tools" module is a module of my own, providing a MQTT client and some other handy stuff - but I think you'll get the picture.
      For geofencing I also used the latlong javascript from http://www.movable-type.co.uk/scripts/latlong.html and changed it into a module.

      Have fun! (sorry, code indenting sucks, blame WP for that 😉

  3. Chris says:

    Thanks Robert.

    I’ll have to read up on MQTT a bit more. I’m not quite understanding ‘what’ is serving the map and coordinates and presenting the ‘published’ info. I think that’s the ‘tools’ module providing an MQQT client and I guess that’s bespoke to your system in other aspects as well. I’m not sure how difficult it will be for someone new to this to create that part. I don’t think you’re using an online MQTT service (broker ?).

    I do have node.js and Apache / PHP / mySQL on the Pi and was looking at moving from the current PHP handling of Btraced data into what you’re writing up here but it may be a step too far with my current knowledge at the moment for me.

    OTOH if you do get the opportunity expand on the MQTT side I’m sure many other people will be interested too. I feel using MQTT could be very useful for other aspects of my HA too so I’d like to know more. I’ll have a read of the MQTT site.

    • Hi Chris,
      Modifying the script to make it all more “standalone” (i.e. less depending on how my system is built and what it provides) should be quite easy actually. Just read the code of ‘some’ Node script that uses the MQTT module and you’ll see a lot of similarities with the script I added to the post. I’m just too lazy to remove some personal stuff from the script (and test if it’s still working, what seems to be forgotten a lot of times) , assuming that the ‘essentials’ are clear…that’s it, basically 🙂
      Maybe the essentials are not that clear as I thought they would be after all.. and since you’re not the first having some trouble, I decided to spend some time this weekend to create a set of scripts/files that will work out of the box with (almost) no modification and some extra instructions. How does that sound?

  4. Chris says:

    That sounds really great.. thanks.

    I’m hoping to get a standalone RapberryPI solution but having said that if MQTT proves useful within other areas of my whole HA system then I envisage I’ll be utilising a PC based component (broker ?) for that too.

    I currently have a Windows server 24/7 running my HA apps although I do try and make everything functional standalone using small embedded devices where possible. It makes things more resilient.

  5. Pingback: The All-in-1 solution for Btraced Track & Trace - Digits Domotica Blog

  6. Pierre says:

    Great articles, thanks for sharing this information. Have you heard about MQTTitude (now OwnTracks)? Basically it’s a client application for Android and iOS that will allow you to track your location and publish it to a MQTT broker. https://github.com/binarybucks/mqttitude

    • Hi Pierre,
      Thanks and yes, I’ve read about it and seen some screenshots, very nice indeed. Without Btraced I would probably be using OwnTracks by now 😉 But since Btraced was made by a friend of mine, I helped testing during beta and because it’s already integrated in the rest of my system it’s unlikely that I will change App. 😉

  7. Eric says:

    Robbert, thanks for putting up this info. I’m already running Mosquitto for some other home automation stuff, and would like to give my family the ability to see where everyone is on the map.

    Is there a forum for this app, for those trying to piece together the node apps on their own server?

    Thanks!

    • Yes, the Btraced app has its own website; just click the link in the post; there you’ll also find the Btraced forum.

      • Eric says:

        Robbert,
        I’m having trouble finding what the MQTT topic Btraced uses to post location data is. In the Btraced app, you specify a server and port, but not a topic name. Something like “btrace/user1” or something like that? Do you know what I mean? I can’t monitor what Btrace is uploading to MQTT if I don’t know what the topic name is.

        • Hi Eric,
          You can enter a username in the Btraced App Upload settings. The App uploads the GPS data including that username you specified in the settings.
          Also see lines 47 and 62 in the code of the Node.JS script. Line 47 retrieves that username from the uploaded data, line 62 uses it to construct the topic name.

          • Eric says:

            Oh, I think I understand now. The server settings that Btraced uses is not the MQTT server. As you mentioned in your writeup, Btraced uses HTTP to post GPS data. So you script takes the HTTP posts and reposts them to a MQTT broker?

            Do I have that right?

  8. Patrick says:

    Hi Robert, how do i need to setup the bwired app? Do you have a trip running continuously to get the realtime data?

Leave a Reply

Your email address will not be published. Required fields are marked *