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.