Hands On
100DaysOfCode

Solutions: Day 81-85 #100DaysOfCode

By Shruti Kuber | 30 June 2020

Try HERE Maps

Create a free API key to build location-aware apps and services.

Get Started

Welcome to week 17 of #100DaysOfCode with HERE. This week we are going to look at a few powerful endpoints of the Fleet Telematics API
If you have no idea what I'm talking about, take a look at this blog post which will tell you everything about #100DaysOfCode. If you have missed the solutions for days 0-80, you can find them in the previous blogs posts or on our YouTube channel.
Let's begin!

Day 81/100

Nicely tucked into the Fleet Telematics API, is the option for getting a route for Electronic Vehicles (EVs). Now, how is a route for an EV any different than a route for a diesel guzzling car? 🙄 Well, for one, the environmental zone restrictions on vehicles depending on the emission type is different. Secondly, you would want to get a route where you can find plenty of electric charging stations. With this end-point, we will go a little deeper. If you specify the consumption details of your EV and give the battery parameters like initial charge, max charge, etc. the Fleet Telematics API gives you a route with suggestions on where you can stop to charge your EV. That's quite neat eh?
So, how do we do it. Two parameters: customConsumptionDetails and batteryParameters. The customConsumptionDetails parameter is similar to the one we used for our diesel truck back on day 77 of #100DaysOfCode. Although here you need to write down the specifics of the charge consumed at different speed levels. This is again in cost/Km where the cost is in the currency you specify.
With batteryParameters, you can write down the current charge of the vehicle , in kWh at the beginning of the journey, battery capacity,charge level at which you want to recharge and the maximum charge you want the battery to be at. This is followed by the charging curve which answers the question - How much power(kW) does your battery spend when it is at a charge level X ?


  let url = `https://fleet.ls.hereapi.com/2/calculateroute.json`+
    `?apikey=${window.hereCreds.JS_KEY}`+
    `&waypoint0=52.53086235,13.38475371`+//Berlin
    `&waypoint1=53.13256,17.98909`+// Warsaw
    `&mode=fastest;car;traffic:disabled`+
    `&departure=2020-06-22T15:01:41`+
    `&customConsumptionDetails=speed,0,0.102,10,0.084,30,0.066,50,0.06,70,0.066,100,0.072,120,0.084,140,0.108;ascent,0.4;descent,0.1`+
    `&batteryParameters=initialCharge:15;maxCharge:33;minChargeAtStop:7;chargingStopDepartureCharge:27;chargingCurve:0,45,20,48,23,50,27,40,28,27,30,15,32,5,33,1`+
    `&routeAttributes=shape`+ 
    `&linkAttributes=-shape`;


  fetch(url)
  .then(response => response.json())
  .then(response => {
    console.log(response);
  }, error =>{
      console.error(error);
  });
  

The waypoint object in the route response comes with a few extra objects with this routing type. Here the object type gives you the type of the waypoint, whether it is a normal stop over or a charging stop over. The object power under the object chargingStationInfo gives the charge of the battery when it reached that point.


  "waypoint": [
          {
              "linkId": "+563894215",
              "mappedPosition": {
                  "latitude": 48.76963,
                  "longitude": 9.1747
              },
              "originalPosition": {
                  "latitude": 48.769606,
                  "longitude": 9.174678
              },
              "spot": 0.0,
              "sideOfStreet": "right",
              "seqNrOnRoute": 0,
              "globalWayPointSeqNr": 0,
              "type": "stopOver",
              "mappedRoadName": "Hauptstätter Straße",
              "shapeIndex": 0
          },
          {
              "linkId": "-749456569",
              "mappedPosition": {
                  "latitude": 49.23369,
                  "longitude": 9.35457
              },
              "originalPosition": {
                  "latitude": 49.23369,
                  "longitude": 9.35462
              },
              "spot": 0.33507,
              "sideOfStreet": "left",
              "seqNrOnRoute": 1,
              "waypointType": "chargingStopOver",
              "type": "stopOver",
              "mappedRoadName": "Wilhelm-Maybach-Straße",
              "chargingStationInfo": {
                  "power": 22.08
              },
              "shapeIndex": 1686
          },

Day 82/100

A classic travelling salesperson problem is what many fleet management companies or even individual drivers face. I have 10 packets to deliver to 10 different locations in the city, In what sequence do I deliver them to obtain efficiency? For this very problem, the Waypoint Sequence API is the perfect and easy solution. As the name suggests, you can give it a starting point and a number of destinations. The API will give you the optimal sequence of the destinations. You can specify if you want to optimize the sequence for time or distance with the parameter improveFor. The sequence gives you the sequence number of the destination in the route. The Waypoint Sequence has another endpoint called findpickups which gives you the sequence of picking up passengers in a ride-pooling situation.


  let url = `https://wse.ls.hereapi.com/2/findsequence.json`+
    `?apiKey=${window.hereCreds.JS_KEY}`+
    `&start=52.53086235,13.38475371`+//Berlin
    `&destination0=52.457213,13.3806209`+// Warsaw
    `&destination1=52.518229,13.315388`+
    `&destination2=52.54830288,13.3634539`+
    `&mode=fastest;car;traffic:disabled`+
    `&improveFor=time`; 

    fetch(url)
    .then(response => response.json())
    .then(response => {
      console.log(response);
    }, error =>{
        console.error(error);
    });

Day 83/100

For day 83 and 84, we are going to explore custom routes. Certain roads, bridges, or private roads do not permit certain types of vehicles. The routing engine will not route through that road geometry. In some situations, you want a route through those restricted roads assuming you have taken appropriate permissions. It could also be the case that your delivery vehicle needs to come further into the building/ warehouse on a private road. For day 83, we are going to upload a private route in the custom route layer. This layer is connected to your API KEY. So, only the apps using this API Key can use this route. You can add this route by adding multiple points along the route. You can store multiple route like this given that they all have unique names. The names of these layers should start with the word OVERLAY. Along with the points in the route, you need to include the name of the layer in which this route will be included as well as the data associated with it. You can get more details about the format here. With this Custom Routes API, you can also get rid of restrictions on existing roads as well as add restrictions on roads.


 let url = `https://fleet.ls.hereapi.com/2/overlays/upload.json`+
    `?apikey=${window.hereCreds.JS_KEY}`+
    `&map_name=OVERLAYIKEA`+
    `&overlay_spec=[{
      "op":"create",
      "shape":[
        [52.46959,13.36809],
          [52.46959,13.36801],
          [52.46960,13.36792],
          [52.46960,13.36781],
          [52.46960,13.36771],
          [52.46961,13.36761],
          [52.46961,13.36751],
          [52.46962,13.36741],
          [52.46962,13.36732]],
      "data":{"NAMES":"IKEA loading Road","TRAVEL_DIRECTION":"B"}
    }]`+
    `&storage=readonly`;

  fetch(url)
  .then(response => response.json())
  .then(response => {
    console.log(response);
  }, error =>{
      console.error(error);
  });

Day 84/100

With day 84, we will calculate a route which includes the custom route from day 83. The call is pretty similar to a regular routing call. What is important is the name of the added layer. This name should be the same as the layer you updated on your API Key. By including this, you will now get a route which includes the added layer. You can take a look at this blog post for another example with custom routes.


  let url = `https://fleet.ls.hereapi.com/2/calculateroute.json`+
    `?apikey=${window.hereCreds.JS_KEY}`+
    `&overlays=OVERLAYIKEA`+// your overlay name
    `&mode=fastest;truck`+
    `&waypoint0=52.45710,13.38058`+
    `&waypoint1=52.46961,13.36730`+
    `&routeAttributes=shape`;

  fetch(url)
  .then(response => response.json())
  .then(response => {
    console.log(response);
  }, error =>{
      console.error(error);
  });

Day 85/100

With day 85, we are going to get a sneak peak into the massive Advanced Data Sets. This gem is, as the name suggests, a huge dataset of advanced map layers that stores information from census data, to building geometries, to POIs to sign posts etc. in the map layer. There are many ways to use this data depending on what your application requires. One of the ways is to request data along a route/ corridor. For day 85, we are going to pass the route from day 81, and get all EV Charging Stations along this route. The corridor here is the route shape while the radius is the distance from the route where the EV charging stations can be. The layer Id specifies the data layer you want to search through. In this case, the layer name is EVCHARGING_POI. The key_attributes here states what properties of this data you want. To know about more layers, and their properties, the Advanced Data Sets lists all data layers, its properties and attributes in the Guide section. For this example, I am using just a part of the route to use the GET call. For longer routes, you need to you the POST call.



  function getEVChargingRoute(){
    let url = `https://fleet.ls.hereapi.com/2/calculateroute.json`+
    `?apikey=${window.hereCreds.JS_KEY}`+
    `&waypoint0=52.53086235,13.38475371`+//HERE Berlin
    `&waypoint1=52.45709,13.38059`+//my Location
    `&mode=fastest;car;traffic:disabled`+ 
    `&routeAttributes=shape`;

    fetch(url)
    .then(response => response.json())
    .then(response => {
    ...
    // pass the route shape of the route from day 81 
    let route = response.response.route[0];
    let routeShape = route.shape;
    searchCorridor(routeShape);
    ... 
    }

  }

  function searchCorridor(corridor){
    let searchUrl = `https://fleet.ls.hereapi.com/1//search/corridor.json`+
      `?apiKey=${window.hereCreds.JS_KEY}`+
      `&corridor=${corridor}`+//
      `&radius=500`+// in meters
      `&layer_ids=EVCHARGING_POI`+
      `&key_attributes=POI_ID`;
  
    fetch(searchUrl)
    .then(result => result.json())
    .then(result => {
      displayEV(result);
    }, err =>{
      console.error(err);
    });
  
  }

That was week 17 of #100DaysOfCode with HERE. This week, we looked at EV routing, Waypoint sequencing, Custom routes and Advanced Data Sets from the Fleet Telematics API. This was just the tip of the iceberg with Fleet Telematics. Feel free to try your hand at more Fleet Telematics endpoints and let us know the ones you found interesting. Meanwhile, keep following us on Twitter for more tasks and complete all 100 days. If you want to watch the video version of these solutions, take a look at our playlist for #100DaysOfCode on YouTube. If you want the code snippets of the APIs covered with #100DaysOfCode, head over to the 100daysofcode GitHub repository.
If you are a fan of IBM Watson, machine learning, location data, python and pizza not particularly in that order, jump to the blog post by our 🥑 Vidhan Bhonsle.
Happy coding!