ES

Mario Rocafull / Albin

Software developer freelance in Valencia

4 October 2023 · Code

How to use Traccar API

Traccar is a real-time vehicle geolocation company. I leave you some functional examples that will save you frustrations.

Although their API is relatively simple, it has been a bit tedious to get it working due to some details omitted from the documentation, how terse their forum responses are, and how confusing the error messages are (which seems like a 'collations' is really an authentication problem). So I have decided to publish what I learned in case it helps someone else.

In this article you will find two ways to obtain the positions using PHP and a common way to display them on a map with Javascript.

Getting the positions with PHP (API v5)

In this version you must first generate a token from the platform itself and then you can use it to identify yourself in subsequent calls.

I show you an image of where to get the token.

And here I leave you a simple code example.

<?

$path   = __DIR__.'/';
$action = $_GET['action'] ?? null;

if($action=='positions') {
	if($curl = curl_init('http://«Your Traccar Server»/api/positions')) {
		$headers = [];
		$headers[] = 'Authorization: Bearer «Your API Token»';

		curl_setopt($curl, CURLOPT_COOKIEFILE,     .'traccar.cookies');
		curl_setopt($curl, CURLOPT_COOKIEJAR,      .'traccar.cookies');
		curl_setopt($curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
		curl_setopt($curl, CURLOPT_CUSTOMREQUEST,  'GET');
		curl_setopt($curl, CURLOPT_HTTPHEADER,     $headers);
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl, CURLINFO_HEADER_OUT,    1);
		$resp = curl_exec($curl);
		$info = curl_getinfo($curl);
		curl_close($curl);
		if($resp!==false && is_string($resp)) {
			header('Content-Type: application/json');
			die($resp);
		} else {
			header('Content-Type: text/plain');
			var_dump($resp, $info);
			die();
		}
	}
}
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="initial-scale=1,width=device-width" />
	<title>Traccar API Demo</title>
	<style>
	body {
		margin : 20px;
		background: #F5F5F5;
	}
	.gmaps {
		aspect-ratio: 16 / 8;
	}
	</style>
</head>
<body>

	<div id="gmaps" class="gmaps"></div>

	<script src="traccar.js"></script>
</body>
</html>

Creating a session and getting the positions with PHP (API v4)

The first step to use the API is to create a session. After this step you will get a Cookie and also a Token that only serves to confuse.

The second step is to obtain the positions of the different registered devices.

Algunos detalles a tener en cuenta.

  • Although the parameter we send is called 'email', it is actually the username, for example 'admin'.
  • In CURL configuration it is important to keep both 'CURLOPT_COOKIEFILE' and 'CURLOPT_COOKIEJAR'.
  • I have left in the code how to recover the token although it has no further use.
<?

$path   = __DIR__.'/';
$action = $_GET['action'] ?? null;

if(empty($action)) {
	if($curl = curl_init('https://«Your Traccar Server»/api/session')) {
		$headers = [];
		$headers[] = 'Content-Type: application/x-www-form-urlencoded';

		curl_setopt($curl, CURLOPT_COOKIEFILE,     .'traccar.cookies');
		curl_setopt($curl, CURLOPT_COOKIEJAR,      .'traccar.cookies');
		curl_setopt($curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
		curl_setopt($curl, CURLOPT_CUSTOMREQUEST,  'POST');
		curl_setopt($curl, CURLOPT_POST,           true);
		curl_setopt($curl, CURLOPT_POSTFIELDS,     http_build_query(['email'=>'«Your user»','password'=>'«Your password»']));
		curl_setopt($curl, CURLOPT_HTTPHEADER,     $headers);
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl, CURLINFO_HEADER_OUT,    1);
		$resp = curl_exec($curl);
		$info = curl_getinfo($curl);
		curl_close($curl);
		if($resp!==false && is_string($resp)) {
			$resp = json_decode($resp);
			if(is_object($resp)) {
				$token = $resp->token;
			} else {
				die(json_last_error_msg());
			}
		} else {
			header('Content-Type: text/plain');
			var_dump($resp, $info);
			die();
		}
	}
}

if($action=='positions') {
	if($curl = curl_init('http://«Your Traccar Server»/api/positions')) {
		$headers = [];
		$headers[] = 'Authorization: Basic '.base64_encode('«Your user»:«Your password»');

		curl_setopt($curl, CURLOPT_COOKIEFILE,     .'traccar.cookies');
		curl_setopt($curl, CURLOPT_COOKIEJAR,      .'traccar.cookies');
		curl_setopt($curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
		curl_setopt($curl, CURLOPT_CUSTOMREQUEST,  'GET');
		curl_setopt($curl, CURLOPT_HTTPHEADER,     $headers);
		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl, CURLINFO_HEADER_OUT,    1);
		$resp = curl_exec($curl);
		$info = curl_getinfo($curl);
		curl_close($curl);
		if($resp!==false && is_string($resp)) {
			header('Content-Type: application/json');
			die($resp);
		} else {
			header('Content-Type: text/plain');
			var_dump($resp, $info);
			die();
		}
	}
}
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="initial-scale=1,width=device-width" />
	<title>Traccar API Demo</title>
	<style>
	body {
		margin : 20px;
		background: #F5F5F5;
	}
	.gmaps {
		aspect-ratio: 16 / 8;
	}
	</style>
</head>
<body>

	<div id="gmaps" class="gmaps"></div>

	<script src="traccar.js"></script>
</body>
</html>

Showing the vehicles on the map

This code for displaying vehicles meets the following guidelines:

  • If a new vehicle appears, a new marker is created
  • If a vehicle disappears, its marker is hidden
  • Check the location of vehicles every 1 second.
  • Keeps all vehicles visible by adjusting the map zoom until the user interacts with the zoom, then the user's decision is respected.
oTracer = {
	markers: {},
	autozoom: true,
	init: function (gmap) {
		this.gmap = gmap;
		this.icon = new google.maps.MarkerImage('/flag0.svg', new google.maps.Size(32, 48), new google.maps.Point(0,0), new google.maps.Point(16, 48));
		this.hint = window.setInterval(this.update.bind(this), 1000);
		this.update();
		google.maps.event.addListener(this.gmap, 'zoom_changed', (e) => {
			this.autozoom = false;
		});
	},
	update: function () {
		fetch('traccar.php?action=positions').then(resp => {
			resp.json().then(info => {
			//	console.log(info);
				info = info.filter(location => location.latitude!==0 && location.longitude!==0);
				const deviceIds = [];
				const bounds = new google.maps.LatLngBounds();
				info.map(location => {
					deviceIds.push(location.deviceId);
					let   marker = this.markers[location.deviceId] ?? null;
					const latlng = new google.maps.LatLng(location.latitude, location.longitude);
					if(marker) {
						marker.setPosition(latlng);
					} else {
						marker = new google.maps.Marker({ map: this.gmap, position: latlng, icon: this.icon,  title: 'Vehículo '+location.deviceId });
						this.markers[location.deviceId] = marker;
					}
					bounds.extend(latlng);
				});
				for(let deviceId in this.markers) {
					deviceId = parseInt(deviceId);
					this.markers[deviceId].setVisible(deviceIds.includes(deviceId));
				}
				if(this.autozoom) {
					this.gmap.fitBounds(bounds); //auto-zoom
					this.gmap.panToBounds(bounds); //auto-center
				}
			});
		});
	},
};

oGMaps = {
	init: function () {
		var elm    = document.querySelector('.gmaps');
		var script = document.createElement('script');
		script.src = '//maps.google.com/maps/api/js?key=«Your Google Maps API Key goes here»';
		script.onload = () => {
			const latlng  = new google.maps.LatLng(40.444, -3.69747);
			const mapopts = { center: latlng, zoom: 6, mapTypeId: google.maps.MapTypeId.ROADMAP };
			const gmaps   = new google.maps.Map(document.querySelector('.gmaps'), mapopts);
			oTracer.init(gmaps);
		}
		document.head.appendChild(script);
	},
};

window.addEventListener('DOMContentLoaded', oGMaps.init.bind(oGMaps));