This tutorial presents how Beebotte can be used to build a Geolocation
tracking application.
In this tutorial we will create a Web Application
that uses HTML5's Geolocation API
to publish and track the location of a mobile phone (or compatible device). We will use Beebotte client API to publish the device location to a predefined channel resource. Then, we will subscribe to that channel resource to receive published location updates in real time and display them on a Google Map
.
This tutorial assumes that you have successfully registered
to Beebotte and obtained your API and Secret keys
.
By the end of this tutorial, you will learn how to:
authentication endpoint
for interacting with BeebotteTutorial contents:
We only need a device with a Geolocation capable browser. Geolocation is most accurate for devices with GPS as smartphones and tablets. For obvious privacy reasons, the device location is not available unless the user approves it.
We will use Node.js
for the application's backend. However, you can use an alternative technology of your choice. Porting the backend should not be an issue.
The structure of the project will be straightforward. We will create the following files:
app.js
: This Node.js code creates a very basic Web Server. It implements the authentication endpoint that will grant your users access to Beebotte (required by the track.html and monitor.html web pages described below).public/monitor.html
: This page will show the Google Maps with a marker that will get updated everytime the location changes.public/track.html
: This page will simply activate/deactivate Geolocation tracking. When Geolocation is activated, the location of the device will be published to Beebotte on specific channel resource
.public/js/monitor.js
: This Javascript file will include the source code that uses the Google Maps API to draw the map and Beebotte API to subscribe to the location channel resource to get notified once a new value is published to Beebotte.public/js/track.js
: This Javascript file will include the source code that contains the functions that retrieve the current location using the Geolocation API and publish it to Beebotte.You can fork the project from its Github repository
.
Beebotte provides a javascript library to add real-time communication between a browser (Web Page) and Beebotte platform. You need to first include the javascript client library in your HTML page.
<script src='socket.io-1.1.0.js'></script> <script src='//beebotte.com/bbt.js' ></script>
Initialize Beebotte by indicating the API Key
associated with your account, and the Authentication Endpoint
to grant your users access to publish data to Beebotte and to subscribe to channel resources.
Remember, you are adding a realtime functionality to your application. Your users are not necessarily on beebotte. It is your responsibility to grant permissions to authenticated users.
var bbt = new BBT('API_KEY', {auth_endpoint: '/auth'});
We will use the Geolocation API of HTML5 to retreive the device location. Geolocation provides two mechanisms for retrieving location:
getCurrentPosition
: gets the current position of the device.watchPosition
: registers a handler that will be called automatically everytime the position changes.In this tutorial, we will use watchPosition
to get position change updates. For one time position retrieval, you can use getCurrentPosition
instead.
// Options object var opts = { enableHighAccuracy: true, timeout: 5000, // timeout before returning the position maximumAge: 0 // get a fresh position } var tracker = null function success (position) { // Do something with location object } function error (error) { alert('Error when getting Geolocation') } if (navigator.geolocation) { tracker = navigator.geolocation.watchPosition( success, // on success function error, // on error function opts // options ) } else { alert('Geolocation is not supported by this browser') }
A watchPosition
handler can be cancelled as follows:
if (tracker != null) { navigator.geolocation.clearWatch(tracker) tracker = null }
Publishing the location messages from the client side requires write permission to be granted. Your application is responsible for granting permissions to your users, this can be accomplished by setting write
to true in the subscription:
/* Request write access to the resource. Permissions are granted at the resource level */ bbt.subscribe({ channel: 'private-mychannel', resource: 'location', read: false, write: true // We need to publish data }, function(msg){ // read access was set to false, we will never get here });
The subscribe
API will first contact the authentication end-point of your application to request write permission for the specified resource. If the permission is granted, it will send its permission grant to Beebotte. After this, you will be able to publish location messages as follows:
bbt.publish({ channel: 'private-mychannel', resource: 'location' }, { 'latitude': latitude, 'longitude': longitude })
This will send a private message on the given channel resource.
Integrating both codes will be as follows:
// Options object var opts = { enableHighAccuracy: true, timeout: 5000, // timeout before returning the position maximumAge: 0 // get a fresh position } function init () { var tracker = null var bbt = new BBT('YOUR_API_KEY', { auth_endpoint: '/auth' }) bbt.subscribe({ channel: 'private-mychannel', // replace this with your channel resource: 'location', // replace this with your channel GPS resource read: false, // No need to subscribe to data we are publishing write: true // We need to publish data }, function(message) {}) function success (position) { var latitude = position.coords.latitude var longitude = position.coords.longitude console.log('publishing position: ', latitude, longitude) bbt.publish({ channel: 'private-mychannel', resource: 'location' }, { 'latitude': latitude, 'longitude': longitude }) } function error (error) { var errors = { 1: 'Permission denied', 2: 'Position unavailable', 3: 'Request timeout' } alert('Error: ' + errors[error.code]) } function startTracking () { if (navigator.geolocation) { tracker = navigator.geolocation.watchPosition( success, error, opts ) } else { alert('Geolocation is not supported by this browser') } } function stopTracking () { if (tracker != null) { navigator.geolocation.clearWatch(tracker) tracker = null } } return { startTracking: startTracking, stopTracking: stopTracking } }
In order to receive Geolocation messages published to your channel resource, you need to register to it first.
As we only want to receive new location messages, we will only request read access.
//Subscribe to a private channel resource bbt.subscribe({ channel: 'private-mychannel', resource: 'location', read: true, write: false }, function(msg){ //Do something with the received message });
To subscribe to real-time data, you need to specify the channel and resource where the data is being published. In this example, we assume the data messages are private (that's why we added the private-
prefix to the channel name). Subscribing to private channels requires explicit authorization.
In order to display the received location on a map, we will use Google Maps API to create the map and to place a marker accordingly. The marker position needs to be updated whenever a new location is received.
We will update the subscribe
code above to create the map and update the marker position. The complete code will be as follows:
function init () { var map = null var marker = null var bbt = new BBT('YOUR_API_KEY', { auth_endpoint: '/auth' }) bbt.subscribe({ channel: 'private-mychannel', resource: 'location', read: true, write: false }, function(msg) { console.log('received position: ', msg.data.latitude, msg.data.longitude) displayLocation(msg.data.latitude, msg.data.longitude) }) // Initialize GoogleMaps map function initializeMap (position) { var options = { zoom: 17, center: position, // center on received position mapTypeId: google.maps.MapTypeId.PLAN } // Assuming 'map' is a valid element id in your DOM map = new google.maps.Map(document.getElementById('map'), options) } // Process received location function displayLocation(lat, lng) { // initialize map at first received location if (!map) { initializeMap(new google.maps.LatLng(lat, lng)) } // remove previous marker if already exists // if marker exists remove it if (marker) { marker.setMap(null) } // set the marker to the new position marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lng), icon: { path: google.maps.SymbolPath.CIRCLE, scale: 8, strokeColor: '#FF0000' }, draggable: false, map: map }) } }
The authentication endpoint is a mechanism that needs to be implemented on your backend to grant your users read and write access to your Beebotte channel resources. The authentication endpoint signs your users subscribe requests. These signatures are then attached to subscriptions sent to Beebotte. For details about the client authentication in Beebotte, you can refer to the following link
.
In Node.js, the authentication endpoint can be implemented as follows:
const bbt = require('beebotte') ... // Replace by your ACCESS and SECRET Keys const bclient = new bbt.Connector({ apiKey: 'YOUR_API_KEY', secretKey: 'YOUR_SECRET_KEY', }) ... app.get( '/auth', function (req, res, next) { const channel = req.query.channel const resource = req.query.resource || '*' const ttl = req.query.ttl || 0 const read = req.query.read === 'true' const write = req.query.write === 'true' const sid = req.query.sid if (!sid || !channel) { return res.status(403).send('Unauthorized') } const retval = bclient.sign( // string to sign `${sid}:${channel}.${resource}:ttl=${ttl}:read=${read}:write=${write}` ) return res.send(retval) }) ...
So far we considered location messages as transient
. This means location will be routed through Beebotte from publishers to subscribers without being saved in Beebotte.
If you wish to save location data for future use (save where you parked your car, car trajects, etc.), you need to create a channel for that puspose.
In your account home page, click on Create New
and follow the instructions to create your channel.
Now instead of publishing
location data to Beebotte, we will write
location data to Beebotte. This allows to save data for future use.
The only code modification you need is the following:
bbt.write({ channel: 'private-mychannel', resource: 'location' }, { 'latitude': latitude, 'longitude': longitude })
In this tutorial we saw how to use Beebotte to track the position of a device using Geolocation API and Google Maps API.
You can fork the project code from its Github repository
and enhance it to:
Find out more about the cool things you can do in the tutorials. Check the demos and start playing with the API for further details.