2020-10-13 00:54:34 +02:00
< ? php
// Notes
// The api key from Scooty's app/account: iPtAHWdOVLEtgkaymXoMHVVg
2020-10-13 01:56:45 +02:00
// Below is the static html to generate the map, it can also be done more dynamically using https://github.com/LuminFire/leaflet-php but that might be overkill
2020-10-13 00:54:34 +02:00
2020-10-14 03:12:30 +02:00
//debugging, enable all error reporting
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);
// error_reporting(E_ALL);
//measure script execution time
$start_time = microtime ( true );
$a = 1 ;
2020-10-13 00:54:34 +02:00
2020-10-13 20:51:29 +02:00
// array of scooters, artist, title, description
global $scooters ;
2020-10-13 00:54:34 +02:00
$scooters = array (
2020-10-13 20:51:29 +02:00
array ( 'https://opencoil.show/test-json.php?scooterID=1' , 'artist name 0' , 'title 0' , 'desciption 0' ),
array ( 'https://opencoil.show/test-json.php?scooterID=2' , 'artist name 1' , 'title 1' , 'desciption 1' ),
array ( 'https://opencoil.show/test-json.php?scooterID=3' , 'artist name 2' , 'title 2' , 'desciption 2' ),
//array('https://platform.tier-services.io/v1/vehicle/fbd739d6-554f-4eaf-bd9c-afe3d501c94b', 'artist name 1', 'title', 'desciption'),
2020-10-13 00:54:34 +02:00
);
2020-10-13 17:39:38 +02:00
2020-10-13 16:59:56 +02:00
2020-10-13 20:51:29 +02:00
// for each scooter in array get the json (TODO, for each, safe to file/database?) $scooters is a multidimensional array: $scooter[0][0] = the first data (api url) of the first scooter, $scooter[1][0] = the first data (api url) of the second scooter, $scooter[0][1] = the artist name of the first scooter etcetc.
2020-10-14 03:12:30 +02:00
//$id = 0; //get the first scooter for now
function saveLatestJSON (){
global $scooters ; //"import" the global variable into the function's scope
//TODO if latestData.json = older than ..2 minutes...call the API again
$id = 0 ; //start id
foreach ( $scooters as $item ) {
$getJSON = callAPI ( $scooters [ $id ][ 0 ]); //abstract callAPI for neater reuse
// GET RID OF JSON DECODE!
$arr = json_decode ( $getJSON , true ); // decode JSON data to PHP associative array
// access values from the associative array
$lat = $arr [ " data " ][ " attributes " ][ " lat " ]; // get lattitude
$lng = $arr [ " data " ][ " attributes " ][ " lng " ]; // get longitude
$pos = $lat . ', ' . $lng ; // construct lat/lon for use in leafet
$lst = $arr [ " data " ][ " attributes " ][ " lastLocationUpdate " ]; // get time of last position
$rnt = $arr [ " data " ][ " attributes " ][ " isRentable " ]; // check if scooter is rentable,
$act = $arr [ " data " ][ " attributes " ][ " state " ]; // check if scooter is ACTIVE or MAINTAINANCE
// access values from the multidimensional $scooters array
$nam = $scooters [ $id ][ 1 ]; // get the artist name
$tit = $scooters [ $id ][ 2 ]; // get the works title
$des = $scooters [ $id ][ 3 ]; // get the works description
//construct json with latest data
$latestData [] = array ( " ID " => $id ,
" lastPos " => $pos ,
" lastLocationUpdate " => $lst ,
" isRentable " => $rnt ,
" state " => $act ,
" name " => $nam ,
" title " => $tit ,
" desc " => $des );
$id ++ ;
}
return $latestData ; //return array
2020-10-13 00:54:34 +02:00
2020-10-14 03:12:30 +02:00
}
// THIS ONLY NEEDS TO RUN EVERY 1 or 2 minutes, possibly in the background, als this should construct historical json as per tom martins post here: https://stackoverflow.com/questions/7895335/append-data-to-a-json-file-with-php/7895384
2020-10-14 21:17:39 +02:00
2020-10-14 03:12:30 +02:00
//TODO make historical json file..
//see: https://stackoverflow.com/questions/7895335/append-data-to-a-json-file-with-php/7895384
//add something like:
// $inp = file_get_contents('./latestData.json');
// $tempArray = json_decode($inp);
// $tempArray[] .= $latestData;
// $jsonData = json_encode($tempArray);
// file_put_contents('./latestData.json', $jsonData);
function makeMarker ( int $id ){ // generate appropriate markers based on latest JSON
$readJSON = file_get_contents ( './latestData.json' ); //read latest data
$arr = json_decode ( $readJSON , true );
$pos = $arr [ $id ][ " lastPos " ]; // get last known position
$lst = $arr [ $id ][ " lastLocationUpdate " ]; // get time of last position
$rnt = $arr [ $id ][ " isRentable " ]; // check if scooter is rentable,
$act = $arr [ $id ][ " state " ]; // check if scooter is ACTIVE or MAINTAINANCE
// access values from the multidimensional $scooters array
$nam = $arr [ $id ][ " name " ]; // get the artist name
$tit = $arr [ $id ][ " title " ]; // get the works title
$des = $arr [ $id ][ " desc " ]; // get the works description
2020-10-13 00:54:34 +02:00
2020-10-13 01:56:45 +02:00
2020-10-13 16:59:56 +02:00
2020-10-13 20:51:29 +02:00
//check scooter status and construct marker with corresponding icon
//check if scooter is rentable
if ( $rnt == true && $act === 'ACTIVE' ){
$marker = 'var scooter' . $id . ' = L.marker([' . $pos . '], {time: "' . $lst . ' " }).addTo(map)
. bindPopup ( " <b>'. $tit .'</b><br>'. $des .'<br>Last updated: '. $lst .'<br>Status: Rentable, Gallery Offline " )
. bindTooltip ( " '. $nam .' " ) . setIcon ( availableIcon ); ' ;
} elseif ( $rnt == false && $act === 'ACTIVE' ) {
$marker = 'var scooter' . $id . ' = L.marker([' . $pos . '], {time: "' . $lst . ' " }).addTo(map)
. bindPopup ( " <b>'. $tit .'</b><br>'. $des .'<br>Last updated: '. $lst .'<br>Status: Rented Out, Gallery Online " )
. bindTooltip ( " '. $nam .' " ) . setIcon ( isRentedIcon ); ' ;
};
//check if scooter is in maintenace
if ( $act !== " ACTIVE " ){
$marker = 'var scooter' . $id . ' = L.marker([' . $pos . '], {time: "' . $lst . ' " }).addTo(map)
. bindPopup ( " <b>'. $tit .'</b><br>'. $des .'<br>Last updated: '. $lst .' " )
. bindTooltip ( " '. $nam .' " ) . setIcon ( isMaintenanceIcon ); ' ;
};
return $marker ;
2020-10-14 03:12:30 +02:00
2020-10-13 20:51:29 +02:00
}
2020-10-13 01:56:45 +02:00
2020-10-13 00:54:34 +02:00
2020-10-14 21:44:05 +02:00
function appendJSON ( $filename , $data ){ // create historical json data for documentation over time
2020-10-14 03:12:30 +02:00
2020-10-14 21:44:05 +02:00
// read the file if present
$handle = @ fopen ( $filename , 'r+' );
// create the file if needed
if ( $handle === null )
{
$handle = fopen ( $filename , 'w+' );
}
if ( $handle )
{
// seek to the end
fseek ( $handle , 0 , SEEK_END );
// are we at the end of is the file empty
if ( ftell ( $handle ) > 0 )
{
// move back a byte
fseek ( $handle , - 1 , SEEK_END );
// add the trailing comma
fwrite ( $handle , ',' , 1 );
// add the new json string
fwrite ( $handle , json_encode ( $data ) . ']' );
}
else
{
// write the first event inside an array
fwrite ( $handle , json_encode ( array ( $data )));
}
// close the handle on the file
fclose ( $handle );
}
}
2020-10-14 03:12:30 +02:00
2020-10-13 16:59:56 +02:00
//// make date time file------
2020-10-13 00:54:34 +02:00
2020-10-13 20:51:29 +02:00
2020-10-13 00:54:34 +02:00
2020-10-14 03:12:30 +02:00
///..mmm one big one? seperate ones, timestamped ones?
2020-10-13 16:59:56 +02:00
// 60 second update interval
2020-10-13 00:54:34 +02:00
2020-10-13 16:59:56 +02:00
// make timestamp file like original python one! to check for updates
// make new custom json:
// scooter 1/marker time1 { lat long }
// time2 { lat long }
// scooter 2/marker time1 { lat long }
// time2 { lat long }
//
//
2020-10-13 00:54:34 +02:00
2020-10-13 16:59:56 +02:00
// for each
// check if lastlocation is different...if update > latest file (map file..)
// check if is rentable
2020-10-13 00:54:34 +02:00
2020-10-13 20:51:29 +02:00
// TODO make two files
// 1: current position and state of scooter, latlong, id, status
// 2: historical json file, contains all scooters, updated everytime php file is loaded (or every 60 sec). No state changes, only lat long and time. even if time does not change
2020-10-13 00:54:34 +02:00
// Custom functions
2020-10-13 01:56:45 +02:00
2020-10-13 00:54:34 +02:00
function callAPI ( $url ){
$curl = curl_init ( $url );
curl_setopt ( $curl , CURLOPT_FAILONERROR , true );
curl_setopt ( $curl , CURLOPT_FOLLOWLOCATION , true );
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $curl , CURLOPT_SSL_VERIFYHOST , false );
curl_setopt ( $curl , CURLOPT_SSL_VERIFYPEER , false );
curl_setopt ( $curl , CURLOPT_HTTPHEADER , array (
'x-api-key: bpEUTJEBTf74oGRWxaIcW7aeZMzDDODe1yBoSxi2' ,
'Content-Type: application/json' ,
)); // set the api key
curl_setopt ( $curl , CURLOPT_USERAGENT , 'ProductionRelease/3.8.2 (app.tier.sharing; build:3.8.2.0; iOS 12.4.4) Alamofire/4.9.1' ); // set user-agent to that of the Tier.app, sniffed by burpsuite
$result = curl_exec ( $curl );
if ( ! $result ){ die ( " Connection Failure " );}
curl_close ( $curl );
return $result ;
}
2020-10-14 03:12:30 +02:00
2020-10-13 00:54:34 +02:00
?>
2020-10-13 01:56:45 +02:00
< html >
< head >
< meta charset = " utf-8 " >
2020-10-13 16:59:56 +02:00
< meta name = " viewport " content = " width=device-width,initial-scale=1.0, maximum-scale=1.0, user-scalable=no " />
< script src = " https://code.jquery.com/jquery-1.12.4.min.js " ></ script >
2020-10-13 01:56:45 +02:00
< link rel = " stylesheet " type = " text/css " href = " https://unpkg.com/leaflet@1.3.3/dist/leaflet.css " >
< script src = 'https://unpkg.com/leaflet@1.3.3/dist/leaflet.js' ></ script >
2020-10-13 16:59:56 +02:00
<!-- icons -->
< script src = " https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js " ></ script >
< script src = " https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js " ></ script >
< link rel = " stylesheet " href = " https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.css " />
< link rel = " stylesheet " href = " https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css " />
< link rel = " stylesheet " href = " https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css " />
< link rel = " stylesheet " href = " https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css " />
< link rel = " stylesheet " href = " https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css " />
< link rel = " stylesheet " href = " https://rawcdn.githack.com/python-visualization/folium/master/folium/templates/leaflet.awesome.rotate.css " />
<!-- begin timeslider -->
< script src = " SliderControl.js " ></ script >
< script src = " http://code.jquery.com/ui/1.9.2/jquery-ui.js " ></ script >
< link rel = " stylesheet " href = " http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css " />
< script src = " //cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.2/jquery.ui.touch-punch.min.js " ></ script >
<!-- end of timeslider -->
2020-10-13 01:56:45 +02:00
< style >
#map {
height : 500 px
}
</ style >
2020-10-13 16:59:56 +02:00
< script >
L_NO_TOUCH = false ;
L_DISABLE_3D = false ;
</ script >
2020-10-13 01:56:45 +02:00
</ head >
< body >
< div id = " map " ></ div >
< script >
2020-10-13 17:04:38 +02:00
// define icons
// prefix: glyphicon = bootstrap, list can be found here: https://getbootstrap.com/docs/3.3/components/
// prefix: fa = fontawesome, list is here: https://fontawesome.com/v4.7.0/cheatsheet/
2020-10-13 16:59:56 +02:00
var availableIcon = L . AwesomeMarkers . icon (
2020-10-13 20:51:29 +02:00
{ " icon " : " wifi " , " iconColor " : " white " , " markerColor " : " purple " , " prefix " : " fa " }
2020-10-13 16:59:56 +02:00
);
var isRentedIcon = L . AwesomeMarkers . icon (
2020-10-13 20:51:29 +02:00
{ " icon " : " hourglass-half " , " iconColor " : " white " , " spin " : " true " , " markerColor " : " pink " , " prefix " : " fa " }
2020-10-13 17:39:38 +02:00
);
var isMaintenanceIcon = L . AwesomeMarkers . icon (
{ " icon " : " wrench " , " iconColor " : " white " , " markerColor " : " black " , " prefix " : " fa " }
2020-10-13 16:59:56 +02:00
);
2020-10-13 01:56:45 +02:00
var map = L . map ( 'map' ) . setView ([ 52.516190 , 13.377693 ], 13 );
var Stamen_Toner = L . tileLayer ( 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.{ext}' , {
attribution : 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' ,
subdomains : 'abcd' ,
minZoom : 0 ,
maxZoom : 20 ,
ext : 'png'
});
map . addLayer ( Stamen_Toner );
2020-10-13 16:59:56 +02:00
2020-10-14 21:44:05 +02:00
//the magic: for each scooter in $scooters array, request status and construct marker
2020-10-13 20:51:29 +02:00
< ? php
2020-10-14 21:17:39 +02:00
2020-10-14 21:44:05 +02:00
$filename = " ./latestData.json " ; //latest locations, 1 entry per scooter
$filename_history = " ./historicalData.json " ; //historical locations
2020-10-14 21:17:39 +02:00
// check how old the latest json is
2020-10-14 21:44:05 +02:00
if ( time () - filemtime ( $filename ) > 60 ) { //if older than 60 seconds
$arrayToEcho = saveLatestJSON ();
//append to historical json
appendJSON ( $filename_history , $arrayToEcho );
2020-10-14 21:17:39 +02:00
$latestData = json_encode ( $arrayToEcho , JSON_FORCE_OBJECT ); // force object accepts 0 as a key for the array and not NULL
file_put_contents ( $filename , $latestData , LOCK_EX );
$id = 0 ; //start id
2020-10-13 20:51:29 +02:00
foreach ( $scooters as $item ) {
echo makeMarker ( $id );
2020-10-14 21:17:39 +02:00
$id ++ ;
}
2020-10-13 20:51:29 +02:00
2020-10-14 21:17:39 +02:00
} else { // file younger than 60 seconds
$id = 0 ; //start id
foreach ( $scooters as $item ) {
echo makeMarker ( $id );
2020-10-13 20:51:29 +02:00
$id ++ ;
}
2020-10-14 21:17:39 +02:00
}
2020-10-13 20:51:29 +02:00
?>
2020-10-13 16:59:56 +02:00
// time slider
//test markers
//var marker1 = L.marker([52.504926, 13.358061], {time: "2020-10-09T08:00:29Z"});
2020-10-13 17:44:25 +02:00
//var marker2 = L.marker([52.506926, 13.358061], {time: "2020-10-09T09:00:29Z"});
//var marker3 = L.marker([52.508926, 13.358061], {time: "2020-10-09T10:00:29Z"});
2020-10-13 16:59:56 +02:00
// var map = marker1;
// layerGroup = L.layerGroup([marker_e7a96a6d6b08479ba6d17d42769e5202]);
2020-10-13 20:51:29 +02:00
layerGroup = L . layerGroup ([ scooter0 , scooter1 , scooter2 ]); //make this dynamic
2020-10-13 16:59:56 +02:00
var sliderControl = L . control . sliderControl ({ layer : layerGroup });
map . addControl ( sliderControl );
sliderControl . startSlider ();
2020-10-13 01:56:45 +02:00
</ script >
</ body >
</ html >
2020-10-14 03:12:30 +02:00
< ? php //end of measuring script execution time
//end clock time in seconds
$end_time = microtime ( true );
//calculate script execution time
$execution_time = ( $end_time - $start_time );
echo " Execution time of script = " . $execution_time . " sec " ;
?>