Difference between revisions of "Manual:GPS-tracking"

From MikroTik Wiki
Jump to: navigation, search
(RouterOS script)
Line 12: Line 12:
 
* RouterOS device with a working GPS module
 
* RouterOS device with a working GPS module
 
* RouterOS v6.40rc30 or above
 
* RouterOS v6.40rc30 or above
 
+
* Set GPS format in RouterOS to '''dd'''
Currently RouterOS only outputs DMS format coordinates, this makes the required PHP code substantially larger, because conversion of coordinate systems is required. Once DD coordinate format will be suppported in RouterOS, the code becomes even simpler.
 
  
 
== RouterOS script ==  
 
== RouterOS script ==  
Line 27: Line 26:
 
:set $lon $("longitude")
 
:set $lon $("longitude")
 
}
 
}
tool fetch mode=http url="http://10.55.8.160/index.php" port=8080 http-method=post \
+
tool fetch mode=http url="http://i.dodies.lv/index.php" port=80 http-method=post http-data=("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}") http-content-type="application/json"  
http-data=("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}") http-content-type="application/json"
 
 
:put ("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}")
 
:put ("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}")
 
}
 
}
Line 35: Line 33:
 
== index.php file ==  
 
== index.php file ==  
  
{{Note|Create an empty directory called *sqlite_db* next to the index.php file.}}
+
{{Note|Create an empty directory called *sqlite_db* next to the index.php file. Make sure that directory and files are writable by the group with chmod -R a+w sqlite_db/}}
  
 
<pre>
 
<pre>
 
<?php
 
<?php
 
// Converting DMS ( Degrees / minutes / seconds ) to decimal format
 
function DMStoDD($deg,$min,$sec)
 
{
 
return $deg+((($min*60)+($sec))/3600);
 
}
 
 
// make sure this directory exists and is writeable. file will be created automatically upon first fetch
 
 
$loc = dirname(__FILE__).'/sqlite_db/coord.db';
 
$loc = dirname(__FILE__).'/sqlite_db/coord.db';
 
$db = new SQLite3($loc,SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
 
$db = new SQLite3($loc,SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
 
$raw = file_get_contents('php://input');
 
$raw = file_get_contents('php://input');
 +
$raw = preg_replace('/\\x00/','',$raw);
 
$data = json_decode($raw);
 
$data = json_decode($raw);
 +
 
if (!empty($data) && is_object($data) && property_exists($data,'lat') && property_exists($data,'lon')){
 
if (!empty($data) && is_object($data) && property_exists($data,'lat') && property_exists($data,'lon')){
 
     if(file_exists($loc)) echo 'exists!'.chr(0xa);
 
     if(file_exists($loc)) echo 'exists!'.chr(0xa);
Line 58: Line 50:
 
             $db->exec('CREATE TABLE coordinates (latitude TEXT, longitude TEXT, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, added TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ');
 
             $db->exec('CREATE TABLE coordinates (latitude TEXT, longitude TEXT, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, added TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ');
 
     }
 
     }
$lat = $lon = '';
+
    $lat = $data->lat;
 
+
    $lon = $data->lon;
// the below section splits DMS coordinates apart and converts them to DD format via above function
 
if(preg_match('/^(N|E|W|S)\ (\d+)\ (\d+)\'\ (\d+\.\d+)/',$data->lat,$result)){
 
$lat = DMStoDD( $result[2], $result[3], $result[4]);
 
}
 
if(preg_match('/^(N|E|W|S)\ (\d+)\ (\d+)\'\ (\d+\.\d+)/',$data->lon,$result)){
 
$lon = DMStoDD( $result[2], $result[3], $result[4]);
 
}
 
 
 
$ins = 'INSERT INTO coordinates (latitude,longitude) VALUES (\''.SQLite3::escapeString($lat).'\',\''.SQLite3::escapeString($lon).'\')';
 
$ins = 'INSERT INTO coordinates (latitude,longitude) VALUES (\''.SQLite3::escapeString($lat).'\',\''.SQLite3::escapeString($lon).'\')';
 
$db->exec($ins);
 
$db->exec($ins);
echo 'added!'.chr(0xa);
 
 
die();
 
die();
 
}
 
}
Line 85: Line 68:
 
<script>
 
<script>
 
var map = L.map('map').setView([0,0], 4);
 
var map = L.map('map').setView([0,0], 4);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
+
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '<a href="http://osm.org/copyright">OSM</a>'}).addTo(map);
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
+
 
}).addTo(map);
 
 
<?php
 
<?php
     $result = $db->query('SELECT latitude,longitude FROM coordinates') or die($db->errorInfo()[2]);; 
+
     if($result = $db->query('SELECT latitude,longitude FROM coordinates')){
 
     echo ' var latlngs = [ ';
 
     echo ' var latlngs = [ ';
 
     while($obj = $result->fetchArray()){
 
     while($obj = $result->fetchArray()){
     echo ' [ ' . $obj['latitude']. ' , '. $obj['longitude'] .' ], ';
+
     echo '["'. $obj['latitude'].'","'.$obj['longitude'].'"],';
 
     }
 
     }
     echo ' ]; ';
+
     echo ']; ';
 +
    } else
 +
    echo('//'.$db->lastErrorMsg().chr(0xa)); 
 +
echo($data);
 
?>
 
?>
 
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
 
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);

Revision as of 11:52, 18 January 2019

The following article explains how to create a simple vehicle tracking system using the RouterOS GPS function and scripting.

Method

This approach uses the recently introduced HTTP POST capability of RouterOS Fetch tool. It allows you to POST any kind of data to a webserver, right from RouterOS command line. Of course, you can use scripting, to fill the POST data with variables. The posted data will be written to an SQLITE3 database (file is created, if it doesn't exist) and then, read from the database and fead into a Leaflet.js PolyLine array. This is a proof of concept example, there is no authentication, security or error handling.

Requirements

  • Webserver of your choice, this example has the server running on port 8080
  • PHP
  • SQLite3 module for PHP
  • RouterOS device with a working GPS module
  • RouterOS v6.40rc30 or above
  • Set GPS format in RouterOS to dd

RouterOS script

You can run this script in the Scheduler tool, to have your coordinates sent every n minutes.

{
:global lat
:global lon
/system gps monitor once do={
:set $lat $("latitude")
:set $lon $("longitude")
}
tool fetch mode=http url="http://i.dodies.lv/index.php" port=80 http-method=post http-data=("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}") http-content-type="application/json" 
:put ("{\"lat\":\"" . $lat . "\",\"lon\":\"" . $lon . "\"}")
}

index.php file

Icon-note.png

Note: Create an empty directory called *sqlite_db* next to the index.php file. Make sure that directory and files are writable by the group with chmod -R a+w sqlite_db/


<?php
$loc = dirname(__FILE__).'/sqlite_db/coord.db';
$db = new SQLite3($loc,SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
$raw = file_get_contents('php://input');
$raw = preg_replace('/\\x00/','',$raw);
$data = json_decode($raw);

if (!empty($data) && is_object($data) && property_exists($data,'lat') && property_exists($data,'lon')){
    if(file_exists($loc)) echo 'exists!'.chr(0xa);
    $src = 'SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'coordinates\'';
    $res = $db->querySingle($src);
    if (count($res)==0){
            $db->exec('CREATE TABLE coordinates (latitude TEXT, longitude TEXT, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, added TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ');
    }
    $lat = $data->lat;
    $lon = $data->lon;
	$ins = 'INSERT INTO coordinates (latitude,longitude) VALUES (\''.SQLite3::escapeString($lat).'\',\''.SQLite3::escapeString($lon).'\')';
	$db->exec($ins);
	die();
}
?>

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
  <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
</head>
<body>
<div id="map" style="width: 800px; height: 600px;"></div>
<script>
var map = L.map('map').setView([0,0], 4);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '<a href="http://osm.org/copyright">OSM</a>'}).addTo(map);

<?php
    if($result = $db->query('SELECT latitude,longitude FROM coordinates')){
    echo ' var latlngs = [ ';
    while($obj = $result->fetchArray()){
    	echo '["'. $obj['latitude'].'","'.$obj['longitude'].'"],';
    }
    echo ']; ';
    } else
     echo('//'.$db->lastErrorMsg().chr(0xa));  
	 echo($data);
?>
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
map.fitBounds(polyline.getBounds());
</script>
</body>
</html>

Result

Gpstracker.png